繁体   English   中英

如何创建 MongoDB 聚合以在数组对象中使用 ObjectIds 查找和添加字段

[英]How do I create a MongoDB aggregate to lookup and add fields using ObjectIds in array objects

使用 Mongo 4.4

我希望查找 collections 并使用聚合将目标集合中的人类可读值添加到源集合。

这适用于单个值,但对于某些查找,ObjectIds 位于 arrays 中的对象中,我无法完成这项工作。 我可以将所有值拉回来,但不能将单个值放在数组对象中。

在这个测试用例中,我有一个包含书籍收藏和订阅者收藏的图书馆数据库。 订阅者有一个结帐条目,其中包含一个对象数组,其中包含对书籍的引用和结帐日期。 我想将书名添加到数组中的每个 object 中。

测试数据库:

书籍收藏:

[
  {
    "_id" : ObjectId("63208c9f0d97eff0cfbefde6"),
    "title" : "There and back again",
    "author" : "Bilbo Baggins",
    "publisher" : "Middle Earth Books"
  },
  {
    "_id" : ObjectId("63208cd10d97eff0cfbeff02"),
    "title" : "Two Towers",
    "author" : "JRR Tolkin",
    "publisher" : "Dude Books"
  },
  {
    "_id" : ObjectId("63208cf10d97eff0cfbeffa3"),
    "title" : "Dune",
    "author" : "Frank Herbert",
    "publisher" : "Classic Books"
  },
  {
    "_id" : ObjectId("63208d1d0d97eff0cfbf0087"),
    "title" : "Old Man's War",
    "author" : "John Scalzi",
    "publisher" : "Old Man Books"
  }
]

订阅者集合:

[
  {
    "_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
    "name" : "Tom",
    "checkouts" : [ 
        {
            "bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
            "checkoutDate" : ISODate("2022-01-01T21:21:20.202Z")
        }, 
        {
            "bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
            "checkoutDate" : ISODate("2022-01-02T21:22:20.202Z")
        }
    ],
    "address" : "123 Somewhere"
  },
  {
    "_id" : ObjectId("63208c4e0d97eff0cfbefc1f"),
    "name" : "Bob",
    "checkouts" : [],
    "address" : "123 Somewhere"
  }, 
  {
    "_id" : ObjectId("63208c640d97eff0cfbefc9a"),
    "name" : "Mary",
    "checkouts" : [],
    "address" : "123 Somewhere Else"
  }

用户 Tom 所需的 Output:

{
    "_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
    "name" : "Tom",
    "checkouts" : [ 
        {
            "bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
            "checkoutDate" : ISODate("2022-01-01T21:21:20.202Z"),
            "title" :  "Two Towers"
        }, 
        {
            "bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
            "checkoutDate" : ISODate("2022-01-02T21:22:20.202Z"),
            "title" : "Old Man's War"
        }
    ],
    "address" : "123 Somewhere",
}

使用此聚合:

db.getCollection('subscribers').aggregate([
  {$match: {_id: ObjectId("63208c2e0d97eff0cfbefb46") } },
  {$lookup: {from: "books", localField: "checkouts.bookId", foreignField: "_id", as: "book_tmp_field" }},
  {$addFields: { "checkouts.title": "$book_tmp_field.title"}},
  {$project: { book_tmp_field: 0}}

])

这是我能得到的最接近的:

{
    "_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
    "name" : "Tom",
    "checkouts" : [ 
        {
            "bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
            "checkoutDate" : ISODate("2022-01-01T21:21:20.202Z"),
            "title" : [ 
                "Two Towers", 
                "Old Man's War"
            ]
        }, 
        {
            "bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
            "checkoutDate" : ISODate("2022-01-02T21:22:20.202Z"),
            "title" : [ 
                "Two Towers", 
                "Old Man's War"
            ]
        }
    ],
    "address" : "123 Somewhere"
}

在执行查找之前,您应该UNWIND checkouts数组。 全部处理完成后,对文档进行分组,得到数组中的checkouts 最后,投影您想要的 output 文档。 像这样:

db.subscribers.aggregate([
  {
    $match: {
      _id: ObjectId("63208c2e0d97eff0cfbefb46")
    }
  },
  {
    "$unwind": "$checkouts"
  },
  {
    $lookup: {
      from: "books",
      localField: "checkouts.bookId",
      foreignField: "_id",
      as: "book_tmp_field"
    }
  },
  {
    $addFields: {
      "checkouts.title": "$book_tmp_field.title"
    }
  },
  {
    $project: {
      book_tmp_field: 0
    }
  },
  {
    "$group": {
      "_id": {
        _id: "$_id",
        address: "$address",
        name: "$name"
      },
      "checkouts": {
        "$push": "$checkouts"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$_id",
          {
            checkouts: "$checkouts"
          }
        ]
      }
    }
  }
])

这是操场链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM