将数组内容过滤到包含$ concatArrays的查询中 [英] Filter Array Content to a Query containing $concatArrays

查看:63
本文介绍了将数组内容过滤到包含$ concatArrays的查询中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于此功能,我有一个要查询的数据集.数据如下:

Given this function, I have a data set that I am querying. The data looks like this:

db.activity.insert(
    {
        "_id" : ObjectId("5908e64e3b03ca372dc945d5"),
        "startDate" : ISODate("2017-05-06T00:00:00Z"),
        "details" : [
            {
                "code" : "2",
                "_id" : ObjectId("5908ebf96ae5003a4471c9b2"),
                "walkDistance" : "03",
                "jogDistance" : "01",
                "runDistance" : "08",
                "sprintDistance" : "01"
            }
        ]
    }
)

db.activity.insert(
    {
        "_id" : ObjectId("58f79163bebac50d5b2ae760"),
        "startDate" : ISODate("2017-05-07T00:00:00Z"),
        "details" : [
            {
                "code" : "2",
                "_id" : ObjectId("58f7948fbebac50d5b2ae7f2"),
                "walkDistance" : "01",
                "jogDistance" : "02",
                "runDistance" : "09",
                "sprintDistance" : ""
            }
        ]
    }
)

使用此功能,多亏了尼尔·伦恩(Neil Lunn),我可以得到所需的输出:

Using this function, thanks to Neil Lunn, I am able to get my desired output:

db.activity.aggregate([
  { "$project": {
    "_id": 0,
    "unique": {
      "$filter": {
        "input": {
          "$setDifference": [
            { "$concatArrays": [ 
              "$details.walkDistance",
              "$details.jogDistance",
              "$details.runDistance",
              "$details.sprintDistance"
            ]},
            []
          ]
        },
        "cond": { "$ne": [ "$$this", "" ] }
      }
    }
  }},
  { "$unwind": "$unique" },
  { "$group": {
    "_id": null,
    "uniqueArray": { "$addToSet": "$unique" }  
  }}
])

但是,我不能在开头添加匹配语句.

However, I cannot add a match statement to the beginning.

db.activity.aggregate([
  {$match: {"startDate" : ISODate("2017-05-06T00:00:00Z"), "details.code": "2" },
  {$unwind: '$details'},
  {$match: {"startDate" : ISODate("2017-05-06T00:00:00Z"), "details.code": "2" },
  { "$project": {
    "_id": 0,
    "unique": {
      "$filter": {
        "input": {
          "$setDifference": [
            { "$concatArrays": [ 
              "$details.walkDistance",
              "$details.jogDistance",
              "$details.runDistance",
              "$details.sprintDistance"
            ]},
            []
          ]
        },
        "cond": { "$ne": [ "$$this", "" ] }
      }
    }
  }},
  { "$unwind": "$unique" },
  { "$group": {
    "_id": null,
    "uniqueArray": { "$addToSet": "$unique" }  
  }}
])

因为它给出了以下错误消息:

Because it gives an error message of:

> $concatArrays only supports arrays, not string

如何修改此查询,以便可以添加$match语句?

How can I modify this query so that a $match statement can be added?

推荐答案

不要 $concatArrays .而是应用 $filter 仅提取匹配的值.如前所述,我们可以使用 $setUnion 改为唯一级联":

Don't $unwind the array you are feeding to $concatArrays. Instead apply $filter to only extract the matching values. And as stated, we can just use $setUnion for the 'unique concatenation' instead:

db.activity.aggregate([
  { "$match": { "startDate" : ISODate("2017-05-06T00:00:00Z"), "details.code": "2" } },
  { "$project": {
    "_id": 0,
    "unique": {
      "$let": {
        "vars": {
          "filtered": {
            "$filter": {
              "input": "$details",
              "cond": { "$eq": [ "$$this.code", "2" ] }
            }  
          }
        },
        "in": {
          "$setDifference": [
            { "$setUnion": [ 
              "$$filtered.walkDistance",
              "$$filtered.jogDistance",
              "$$filtered.runDistance",
              "$$filtered.sprintDistance"
            ]},
            [""]
          ]
        } 
      }
    }
  }},
  { "$unwind": "$unique" },
  { "$group": {
    "_id": null,
    "uniqueArray": { "$addToSet": "$unique" }  
  }}
])

使用 $let 可使语法更简洁明智的做法是,您无需指定多个 $map $filter 语句内联"作为 $setUnion

Using $let makes things a bit cleaner syntax wise since you don't need to specify multiple $map and $filter statements "inline" as the source for $setUnion

这篇关于将数组内容过滤到包含$ concatArrays的查询中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆