1

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

{
  "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"

  }]
},

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

4

2 回答 2

2

更好地使用聚合框架,您需要在其中运行包含以下管道步骤(按给定顺序)的操作:

  1. $unwind- 这个初始步骤将展平items数组,即它为每个数组条目生成每个文档的副本。这对于将文档进一步处理为“非规范化”文档是必要的,您可以将其聚合为组。
  2. $group- 这将按item子文档键对展开的文档进行分组,并ids使用$push累加器运算符创建列表。

- 更新 -

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

以下示例演示了这一点:

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" }
    ]
}

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

例如:

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);
于 2016-09-23T15:15:51.567 回答
0

这是使用聚合管道的解决方案:

    db.col.aggregate([
        {
            $unwind: "$items"
        },
        {
            $project: {
                id: 1,
                item: "$items.item"
            }
        },
        {
            $group: {
                _id: "$item",
                ids: {
                    $push: "$id"
                }
            }
        }
    ])
于 2016-09-23T15:15:52.727 回答