我需要从数据库中以JSON的形式检索整个单对象层次 struct .事实上,如果能提出任何其他解决方案来实现这一结果,我们将不胜感激.我决定使用MongoDB及其$lookup支持.

所以我有三个系列:

party

{ "_id" : "2", "name" : "party2" }
{ "_id" : "5", "name" : "party5" }
{ "_id" : "4", "name" : "party4" }
{ "_id" : "1", "name" : "party1" }
{ "_id" : "3", "name" : "party3" }    

address

{ "_id" : "a3", "street" : "Address3", "party_id" : "2" }
{ "_id" : "a6", "street" : "Address6", "party_id" : "5" }
{ "_id" : "a1", "street" : "Address1", "party_id" : "1" }
{ "_id" : "a5", "street" : "Address5", "party_id" : "5" }
{ "_id" : "a2", "street" : "Address2", "party_id" : "1" }
{ "_id" : "a4", "street" : "Address4", "party_id" : "3" }

addressComment

{ "_id" : "ac2", "address_id" : "a1", "comment" : "Comment2" }
{ "_id" : "ac1", "address_id" : "a1", "comment" : "Comment1" }
{ "_id" : "ac5", "address_id" : "a5", "comment" : "Comment6" }
{ "_id" : "ac4", "address_id" : "a3", "comment" : "Comment4" }
{ "_id" : "ac3", "address_id" : "a2", "comment" : "Comment3" }

我需要检索所有相关方的所有地址和地址 comments ,作为记录的一部分.我的汇总:

db.party.aggregate([{
    $lookup: {
        from: "address",
        localField: "_id",
        foreignField: "party_id",
        as: "address"
    }
},
{
    $unwind: "$address"
},
{
    $lookup: {
        from: "addressComment",
        localField: "address._id",
        foreignField: "address_id",
        as: "address.addressComment"
    }
}])

结果很奇怪.有些唱片还可以.但_id: 4人的派对不见了(没有地址).此外,结果集中有两个参与方_id: 1(但地址不同):

{
    "_id": "1",
    "name": "party1",
    "address": {
        "_id": "2",
        "street": "Address2",
        "party_id": "1",
        "addressComment": [{
            "_id": "3",
            "address_id": "2",
            "comment": "Comment3"
        }]
    }
}{
    "_id": "1",
    "name": "party1",
    "address": {
        "_id": "1",
        "street": "Address1",
        "party_id": "1",
        "addressComment": [{
            "_id": "1",
            "address_id": "1",
            "comment": "Comment1"
        },
        {
            "_id": "2",
            "address_id": "1",
            "comment": "Comment2"
        }]
    }
}{
    "_id": "3",
    "name": "party3",
    "address": {
        "_id": "4",
        "street": "Address4",
        "party_id": "3",
        "addressComment": []
    }
}{
    "_id": "5",
    "name": "party5",
    "address": {
        "_id": "5",
        "street": "Address5",
        "party_id": "5",
        "addressComment": [{
            "_id": "5",
            "address_id": "5",
            "comment": "Comment5"
        }]
    }
}{
    "_id": "2",
    "name": "party2",
    "address": {
        "_id": "3",
        "street": "Address3",
        "party_id": "2",
        "addressComment": [{
            "_id": "4",
            "address_id": "3",
            "comment": "Comment4"
        }]
    }
}

请帮帮我.我对MongoDB很陌生,但我觉得它可以满足我的需求.

推荐答案

你"麻烦"的原因是第二个聚合阶段——{ $unwind: "$address" }.它删除了参与方_id: 4的记录(因为它的地址数组是空的,正如您所提到的),并为参与方_id: 1_id: 5生成两条记录(因为它们每个都有两个地址).

  • 为了防止删除没有地址的参与方,您应该将$unwind stage的preserveNullAndEmptyArrays选项设置为true.

  • 为了防止不同地址的参与方重复,您应该在管道中添加$group聚合阶段.此外,使用$project stage和$filter运算符排除输出中的空地址记录.

db.party.aggregate([{
  $lookup: {
    from: "address",
    localField: "_id",
    foreignField: "party_id",
    as: "address"
  }
}, {
  $unwind: {
    path: "$address",
    preserveNullAndEmptyArrays: true
  }
}, {
  $lookup: {
    from: "addressComment",
    localField: "address._id",
    foreignField: "address_id",
    as: "address.addressComment",
  }
}, {
  $group: {
    _id : "$_id",
    name: { $first: "$name" },
    address: { $push: "$address" }
  }
}, {
  $project: {
    _id: 1,
    name: 1,
    address: {
      $filter: { input: "$address", as: "a", cond: { $ifNull: ["$$a._id", false] } }
    } 
  }
}]);

Mongodb相关问答推荐

MongoDB:从集合页面数据中提取不同的值

MongoDB索引使用

$mod只支持数字类型,不支持MongoDb中的array和int

筛选出嵌套数组中的记录Mongo DB聚合

获取文档字段名并将其作为嵌套字段添加到聚合中

当日期和时间在不同键的字符串中时,Mongo 查询过滤今天的数据

减法聚合Mongo文档Golang

避免在 MongoDB 聚合框架中使用 ISODate() 以便管道可以是纯 JSON

使用 mongo-driver/mongo 使用键/值对中的值表达式查找文档

MongoDB 聚合使用 $match 和 $expr 和数组

MongoDB聚合 - 用另一个数组过滤数组

Stripe:必须提供来源或客户

如何在 MongoDb 中使用杰克逊将日期字段存储为 ISODate()

Spring Mongodb @DBREF

.NET 中的 Mongodb 单元测试

如何使用原子操作在一个文档中切换布尔字段?

在 mongodb 的一次更新调用中推送到两个单独的数组

NoSQL:MongoDB 或 BigTable 并不总是 Available意味着什么

MongoDB:查询和检索嵌入式数组中的对象?

更新时提示Field name duplication not allowed with modifiers