使用子查询在MongoDB中创建查询时遇到问题

时间:2016-09-23 15:03:14

标签: javascript mongodb mongodb-query aggregation-framework mongodb-aggregation

我有一个看起来像这样的数据集:

{
  "id": "02741544",
  "items": [{
    "item": "A"
  }]
}, {
  "id": "02472691",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }, {
    "item": "C"
  }]
}, {

  "id": "01316523",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }]
}, {
  "id": "01316526",
  "items": [{
    "item": "A"
  }, {
    "item": "B"
  }]
}, {
  "id": "01316529",
  "items": [{
    "item": "A"
  }, {
    "item": "D"
  }]
},

我正在尝试创建一个查询,它会给我一个如下所示的输出:

{
  "item": "A",
  "ids": [{
    "id": "02741544"

  }, {
    "id": "02472691"

  }, {
    "id": "01316523"

  }, {
    "id": "01316526"

  }, {
    "id": "01316529"

  }]
}, {
  "item": "B",
  "ids": [{
    "id": "02472691"

  }, {
    "id": "01316523"

  }, {
    "id": "01316526"

  }]
}, {
  "item": "C",
  "ids": [{
    "id": "02472691"

  }]
}, {
  "item": "D",
  "ids": [{
    "id": "02472691"

  }]
},

基本上,我正在尝试从对象中的item数组中获取不同的项,然后为每个obj返回一个id数组,其中包含该项的数组。

2 个答案:

答案 0 :(得分:2)

更好地使用aggregation framework运行包含以下管道步骤(按给定顺序)的操作:

  1. $unwind - 此初始步骤将展平items数组,即它会为每个数组条目生成每个文档的副本。这对于在管道中进一步处理文档是必要的,因为"非规范化"您可以汇总为组的文档。
  2. $group - 这会按照item子文档密钥对展平的文档进行分组,并使用 {{3}创建ids列表} 累加器运算符。
  3. - 更新 -

    正如@AminJ在评论中指出的那样,如果items可能有重复的项目值,并且您不希望结果中出现重复的ID,则可以使用 $push 而不是 $addToSet

    以下示例演示了这一点:

    db.collection.aggregate([   
        { "$unwind": "$items" },
        {
            "$group": {
                "_id": "$items.item",
                "ids": { 
                    "$push": { "id": "$id" } /* or use 
                    "$addToSet": { "id": "$id" } if you don't want duplicate ids */                    
                }
            }
        }
    ])
    

    示例输出

    {
        "_id" : "A",
        "ids" : [ 
            { "id" : "02741544" }, 
            { "id" : "02472691" }, 
            { "id" : "01316523" }, 
            { "id" : "01316526" }, 
            { "id" : "01316529" }
        ]
    }
    
    /* 2 */
    {
        "_id" : "B",
        "ids" : [ 
            { "id" : "02472691" }, 
            { "id" : "01316523" }, 
            { "id" : "01316526" }
        ]
    }
    
    /* 3 */
    {
        "_id" : "C",
        "ids" : [ 
            { "id" : "02472691" }
        ]
    }
    
    /* 4 */
    {
        "_id" : "D",
        "ids" : [ 
            { "id" : "01316529" }
        ]
    }
    

    $push函数的结果是聚合管道操作最后阶段生成的文档的游标。因此,如果您希望结果在数组中,您可以使用光标的 aggregate() 方法,该方法返回包含其中所有文档的数组。

    例如:

    var pipeline = [    
            { "$unwind": "$items" },
            {
                "$group": {
                    "_id": "$items.item",
                    "ids": { 
                        "$push": { "id": "$id" } /* or use 
                        "$addToSet": { "id": "$id" } if you don't want duplicate ids */                    
                    }
                }
            }
        ],
        results = db.collection.aggregate(pipeline).toArray();
    
    printjson(results);
    

答案 1 :(得分:0)

以下是使用汇总管道的解决方案:

    db.col.aggregate([
        {
            $unwind: "$items"
        },
        {
            $project: {
                id: 1,
                item: "$items.item"
            }
        },
        {
            $group: {
                _id: "$item",
                ids: {
                    $push: "$id"
                }
            }
        }
    ])