根据根文档结构组合查找并嵌入相同的MongoDB集合

时间:2017-12-06 14:35:46

标签: mongodb join

我想通过以下方式对Mongo进行条件查找:根文档包含customerId集合的链接(customers)或直接嵌入客户,如下所示:

{
  "_id" : 1,
  "item": "item1",
  "customer": { _id: 1, "name": "Jane Doe" }
},
{
   "_id":  2,
   "item": "item2",
   "customerId": 1
}

客户收藏:

{ _id: 1, "name": "Jane Johnson" }

customers集合存储当前版本的客户;为了保持一致性,items集合的成员将只包含客户ID。但是,如果我要冻结某个项目,以便它在某个时间保存其客户的版本,我会将customer直接嵌入到相关的item中。

搜索items时,我希望它们统一显示(即无论客户是否被查找或嵌入,它都会显示为嵌入字段): e.g。

[{
  "_id" : 1,
  "item": "item1",
  "customer": { _id: 1, "name": "Jane Doe" } // historical version of Jane (embedded)
},
{
   "_id":  2,
   "item": "item2",
   "customer": { _id: 1, "name": "Jane Johnson" } // current version of Jane by lookup
}]

问题1:这是正确的方法,如果不是,处理此类案件的最佳做法是什么? 问题2:如果我的方法是正确的,如何最好地使用聚合框架来实现这一目标? 谢谢!

1 个答案:

答案 0 :(得分:0)

答案:

  1. 是的,您可以使用aggregation framework来实现它,这是可能的解决方案之一(另一种可能的解决方案是在您的程序中实现它)。

  2. 只需使用$lookup(用于从其他集合合并数据)和$project(用于最终结果生成)管道阶段。

  3. 查询示例:

    db.getCollection('items').aggregate([
        {
            $lookup: {
                from: "customers",
                localField: "customerId",
                foreignField: "_id",
                as: "customerData"
            }
        },
        {
            $project: {
                "item": 1,
                "customer": {
                    $cond: {
                        if: {$gt: [{$size: "$customerData"}, 0]},
                        then: {$arrayElemAt: ["$customerData", 0]},
                        else: "$customer"
                    }
                }
           }
        }
    ]);