$ lookup与嵌套文档

时间:2018-11-27 11:15:44

标签: arrays node.js mongodb mongodb-query aggregation-framework

我需要加入/查找三个集合。 “组” “用户” “链接的标签” “照片”

我要从集合组中获取所有组。

group {
    id: 1,
    start: 10.12,
    linkedUsers : [1,2,3,4,5]
}

然后我需要从用户中查找/加入

user {
    id: 1,
    name: ""
}

然后从linkedTags

tag {
    userId: 1,
    rounds: 3,
    time: 180
}

然后从“照片”中获取

photo {
    userId: 1,
    location: ""
}

所以我需要这样:

Group {
    id: 1,
    start: 10.12,
    linkedUsers: [1,2,3,4],
    users: [
        1:{
            id: 1,
            name: "",
            rounds: 3,
            time: 180,
            photos: [
                1: {
                    id: 1,
                    location: ""
                }
            ]
        }
    ]
}

这是我到目前为止尝试过的。我认为我需要分阶段进行,但是我还没有弄清楚该怎么做。

  db('groups').aggregate([
    {
      $lookup: {
        from: 'users',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'users'
      }
    },
    {
      $unwind: "$users"
    },
    {
      $lookup: {
        from: 'photos',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'photos'
      }
    },
    {
      $unwind: "$photos"
    },
    {
      $lookup: {
        from: 'linkedTags',
        localField: 'linkedUsers',
        foreignField: 'id',
        as: 'tags'
      }
    },
    {
      $unwind: "$tags"
    },
    { $group: {
        _id: null,
        id: "$id",
        start: '$start',
        linkedUsers: "$linkedUsers",
        users: {$push: {
          id: "$users.id",
          name: "$users.name",
          rounds: "$tags.rounds",
          time: "$tags.time",
          photos: {$push: {
            id: "$photos.id",
            location: "photos.location"
          }}
        }}
    }}
  ])

编辑1: 这是我遇到的第一个错误:

MongoError:字段“ id”必须是累加器对象

我已经读过了,但是我不明白它们是如何融合在一起的。

修改2: 我通过将分组包装在_id中来解决此问题:{}

现在我遇到无法识别的表达式'$ push'

修改3: 在Atlas 4.0.4 Enterprise上运行。

2 个答案:

答案 0 :(得分:1)

我试图创建一个样本关系转储数据

检查工作示例here

尝试按_id分组,然后仅分配photos: $photos

第二级$push是您遇到的问题。

db.groups.aggregate([
  {
    $unwind: "$linkedUsers"
  },
  {
    $lookup: {
      from: "users",
      localField: "linkedUsers",
      foreignField: "_id",
      as: "users"
    }
  },
  {
    $unwind: "$users"
  },
  {
    $lookup: {
      from: "photos",
      localField: "linkedUsers",
      foreignField: "userId",
      as: "photos"
    }
  },
  {
    $unwind: "$photos"
  },
  {
    $lookup: {
      from: "tags",
      localField: "linkedUsers",
      foreignField: "userId",
      as: "tags"
    }
  },
  {
    $unwind: "$tags"
  },
  {
    $group: {
      _id: "$_id",
      "start": {
        $first: "$start"
      },
      "linkedUsers": {
        $first: "$linkedUsers"
      },
      "users": {
        "$push": {
          "id": "$users._id",
          "name": "$users.name",
          "rounds": "$tags.rounds",
          "time": "$tags.time",
          "photos": "$photos"
        }
      }
    }
  }
])

在创建手动数据后,您可能需要对实现进行一些键或数据库名称的更改。


  

注意:-

     

我建议在使用多级preserveNullAndEmptyArrays时使用$unwind。如果找不到内部级别,您可以通过它提供原始文档。

{ $unwind: { path: "$tags", preserveNullAndEmptyArrays: true } } 

希望这对您有所帮助。

答案 1 :(得分:1)

您可以使用以下汇总

db.group.aggregate([
  { "$lookup": {
    "from": "users",
    "let": { "linkedUsers": "$linkedUsers" },
    "pipeline": [
      { "$match": { "$expr": { "$in": ["$_id", "$$linkedUsers"] } } },
      { "$lookup": {
        "from": "tags",
        "let": { "userId": "$_id" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$userId", "$$userId"] } } }
        ],
        "as": "tags"
      }},
      { "$lookup": {
        "from": "photos",
        "let": { "userId": "$_id" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$userId", "$$userId"] } } }
        ],
        "as": "photos"
      }}
    ],
    "as": "linkedUsers"
  }}
])

编辑:已删除变量中的空白