MongoDB ManytoMany集合使用猫鼬聚合,从不同集合中获取值

时间:2020-03-19 05:31:29

标签: node.js mongodb mongoose

我的mongoDB中有3个集合

  1. 用户(姓名,地址等)
  2. 任务(名称,图标,受让人)
  3. UserTask(User.ObjectId,Task.ObjectId,日期)

用户集合:

{
    "users": [
        {
            "name": "Bill",
            "phone": "345"
        },
        {
            "name": "Steve",
            "phone": "123"
        },
        {
            "name": "Elon",
            "phone": "567"
        }
    ]
}

前任务集合:

{
    "tasks": [
        {
            "name": "Run 100m",
            "icon": "run"
        },
        {
            "name": "Walk 1 hour",
            "icon": "walk"
        },
        {
            "name": "Jog 30 minutes",
            "icon": "jog"
        }
    ]
}

UserTasks:

{
    "_id": "5e72fec..",
    "user": "5e72fa4..",
    "task": "5e72fbac..",
    "date": "2020-03-03T05:10:10.000Z",
    "createdAt": "2020-03-19T05:10:37.027Z",
    "updatedAt": "2020-03-19T05:10:37.027Z",
    "__v": 0
},
{
    "_id": "5e72fed3..",
    "user": "5e72fa4e..",
    "task": "5e72fbac..",
    "date": "2020-03-12T05:10:10.000Z",
    "createdAt": "2020-03-19T05:10:43.296Z",
    "updatedAt": "2020-03-19T05:10:43.296Z",
    "__v": 0
},
{
    "_id": "5e72fed6..",
    "user": "5e72fa..",
    "task": "5e72fb..",
    "date": "2020-03-15T05:10:10.000Z",
    "createdAt": "2020-03-19T05:10:46.057Z",
    "updatedAt": "2020-03-19T05:10:46.057Z",
    "__v": 0
},
{
    "_id": "5e72feda...",
    "user": "5e72fa4..",
    "task": "5e72fb..",
    "date": "2020-03-07T05:10:10.000Z",
    "createdAt": "2020-03-19T05:10:50.785Z",
    "updatedAt": "2020-03-19T05:10:50.785Z",
    "__v": 0
},

用户和任务在UserTask集合中包含objectId。我想从下面的用户任务中得到回复

{
    "userTasks": [
      {
        "name": "Walk",
        "icon": "style",
        "assignee": "Steve",
        "log": [
          {
            "name": "Bill",
            "date": "2018-03-15"
          },
          {
            "name": "Elon",
            "date": "2018-02-27"
          },
          {
            "name": "Steve",
            "date": "2018-01-02"
          }
        ]
      },
      {
        "name": "Run",
        "icon": "running",
        "assignee": "Elon",
        "log": [
          {
            "name": "Bill",
            "date": "2019-03-12"
          },
          {
            "name": "Steve",
            "date": "2018-03-03"
          },
          {
            "name": "Elon",
            "date": "2018-03-01"
          }
        ]
      }
    ]
  }

我该如何实现?这是Mongodb中最好的方法吗?我习惯于关系数据库(SQL等)

1 个答案:

答案 0 :(得分:1)

  1. 如何获得此结果?
db.collection.aggregate([
    {
        $lookup: {
            from: "tasks",
            localField: "task",
            foreignField: "_id",
            as: "matchedTask"
        }
    },
    {
        $unwind: "$matchedTask"
    },
    {
        $lookup: {
            from: "users",
            localField: "user",
            foreignField: "_id",
            as: "matchedUser"
        }
    },
    {
        $unwind: "$matchedUser" //can there be tasks with no users? if so we need to tweak this.
    },
    {
        $group: {
            _id: "$matchedTask._id",
            name: {$first: "$matchedTask.name"},
            icon: {$first: "$matchedTask.icon"},
            assignee: "???", // what is this field suppose to be?
            log: {
                $push: {
                    name: "$matchedUser.name",
                    date: "$date"
                }
            }

        }
    }
])
  1. 这是Mongo的最佳方法吗?

绝对不是,Mongo不喜欢连接数据,它的构建不像关系数据库那样工作。 $lookup甚至在Mongo的头几年都不存在。

在Mongo中,数据复制不是一个脏话,实际上是建议这样做。

如果您想提高性能(和更简单的代码),我建议您将这三个集合合并为一个。

**请记住,这是我的看法,我敢肯定您会遇到另外50个人说另外50件事。