mongodb-展开嵌套的子文档

时间:2018-08-13 00:17:47

标签: javascript mongodb mongoose aggregation-framework

对于以下数据集示例:

列表

{ _id: 1, included_lists: [ 2 ], items: [ "i1" ]}
{ _id: 2, included_lists: [], items: [ "i2", "i3" ]}

项目

{ _id: "i1", details: [{}, {}, {}]}
{ _id: "i2", details: [{}, {}, {}]}
{ _id: "i3", details: [{}, {}, {}]}

我想获取列表中的所有项目,包括附加在included_lists上的项目

例如:如果我们查看列表_id 1,我们应该得到项目i1, i2, i3

我有一个方法,涉及使用populate$lookup,但是我不确定如何解开items中嵌套的included_lists并与原始列表中的items一起加入。

最后,我希望有一个可以使用limitskipmatch的数据集。

我正在使用猫鼬,但是香草mongodb代码也可以。

更新

我目前的做法是首先在一个查询中检索所有列表ID,即

List.find({ _id: id}, { included_lists: 1})

然后使用列表ID对该数组进行数组,即

var all_ids = [id, ...included_lists]

然后只需找到物品并放松

伪代码:

List
    .aggregate([
        {
            $match: {
                _id: {
                    $in: all_ids
                }
            }
        },
        { $lookup: {} }
        {
            $unwind: "$items"
        },
        {
            $project: {
                "list.name": 1,
                "list._id": 1,
                "items": 1
            }
        }
    ])

但是我不想做第一个查询来检索所有list_id,我应该能够仅通过一个_id检索所有相关项,然后再检索其余的项。 included_lists

中的项目

2 个答案:

答案 0 :(得分:1)

您可以尝试从mongodb 3.6及更高版本进行以下聚合

List.aggregate([
  { "$match": { "_id": id }},
  { "$lookup": {
    "from": Items.collection.name,
    "let": { "items": "$items" },
    "pipeline": [
      { "$match": { "$expr": { "$in": [ "$_id", "$$items" ] } } }
    ],
    "as": "items"
  }},
  { "$lookup": {
    "from": Lists.collection.name,
    "let": { "included_lists": "$included_lists", "items": "$items" },
    "pipeline": [
      { "$match": { "$expr": { "$in": [ "$_id", "$$included_lists" ] } } },
      { "$lookup": {
        "from": Items.collection.name,
        "let": { "items": "$items" },
        "pipeline": [
          { "$match": { "$expr": { "$in": [ "$_id", "$$items" ] } } }
        ],
        "as": "items"
      }},
      { "$project": { "allItems": { "$concatArrays": [ "$$items", "$items" ]}}}
    ],
    "as": "included_lists"
  }},
  { "$unwind": "$included_lists" },
  { "$replaceRoot": { "newRoot": "$included_lists" }}
])

答案 1 :(得分:1)

您可以尝试在3.4中进行以下汇总。

最初的$lookup用于获取included_lists的项目值,然后是$concatArrays以合并所查找的项目和项目。

第二个$lookup获取项目详细信息,然后$unwind统一结果。

List.aggregate([
{"$lookup":{
  "from":name of the list collection,
  "localField":"included_lists",
  "foreignField":"_id",
  "as":"included_items"
}},
{"$unwind":"$included_items"},
{"$project":{"allItems":{"$concatArrays":["$items","$included_items.items"]}}},
{"$lookup":{
  "from":name of the item collection,
  "localField":"allItems",
  "foreignField":"_id",
  "as":"lookedup_items"
}},
{"$unwind":"$lookedup_items"},
{"$skip": some number},
{"$limit": some number}
])