使用 mongodb 聚合获取父子关系

Posted

技术标签:

【中文标题】使用 mongodb 聚合获取父子关系【英文标题】:Get parent to child relation with mongodb aggregation 【发布时间】:2019-10-09 16:16:32 【问题描述】:

我有一个名为“位置”的集合。在这个集合中,所有子集合和父集合都是商店。现在我想创建一个查询,将我的父级返回到子级逗号分隔字符串。

收藏

businessId:  type: mongoose.Schema.Types.ObjectId, ref: 'admin' ,
parentId:  type: mongoose.Schema.Types.ObjectId, ref: 'location' ,
name:  type: String ,
image:  type: String ,
imageManipulation:  type: String ,
locationColor: [ range:  type: String , color:  type: String  ],
area: ,
settings: ,
status:  type: String, enum: [0, 1], default: 1 ,
isChild:  type: String, enum: [0, 1] ,
parentPosition:  type: String 

在上面的集合中,可以看到parentId字段。如果该位置是一个孩子,那么它有parentId。如果该位置是父位置,则 parentId 将为空。父位置可以N级子位置。

收集数据

[
    "_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
    "name": "Test",
    "settings": 
        "zoom": "3",
        "positionX": "69",
        "positionY": "69",
        "width": "500",
        "height": "334"
    ,
    "parentId": null,
    "image": "1558509637101.jpg",
    "status": "0",
    "businessId": ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor": [],
    "updatedAt": ISODate("2019-05-22T12:59:26.013Z"),
    "createdAt": ISODate("2019-05-22T07:20:37.112Z"),
    "__v": 0
,


    "_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
    "name": "Test sub 1",
    "settings": 
        "zoom": "3",
        "positionX": "48",
        "positionY": "3",
        "width": "500",
        "height": "334"
    ,
    "area": "",
    "parentId": ObjectId("5ce4f84547e90a0b9c3c4763"),
    "image": "1558514863396.jpg",
    "status": "0",
    "businessId": ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor": [],
    "updatedAt": ISODate("2019-05-22T12:59:21.883Z"),
    "createdAt": ISODate("2019-05-22T08:47:43.421Z"),
    "__v": 0
,

    "_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
    "name": "Test Sub 2",
    "settings": 
        "zoom": "5",
        "positionX": "0",
        "positionY": "0",
        "width": "500",
        "height": "334"
    ,
    "area": "",
    "parentId": ObjectId("5ce50caf09359e1b8ccf5c79"),
    "image": "1558526327126.jpg",
    "businessId": ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor": [],
    "updatedAt": ISODate("2019-05-22T11:58:47.147Z"),
    "createdAt": ISODate("2019-05-22T11:58:47.147Z"),
    "__v": 0
]

预期结果

测试,测试子 1,测试子 2

JSON 格式的预期结果

[
    "_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
    "name": "Test",
,

    "_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
    "name": "Test, Test sub 1",
,

    "_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
    "name": "Test, Test sub 1, Test Sub 2",
]

【问题讨论】:

能否以 JSON 格式显示上述示例数据生成的结果。 你使用的是哪个 mongo 版本? @tomslabbaert 我使用的是 3.4 mongo 版本 并且您希望返回值已经是字符串并且根本不使用代码?一个数组就够了吗? @Fanpark 我编辑问题并添加为 JSON 中的预期结果。请检查 【参考方案1】:

你基本上需要$graphLookup 来对同一个集合进行递归循环。

db.location.aggregate([
   "$graphLookup": 
    "from": "location",
    "startWith": "$parentId",
    "connectFromField": "parentId",
    "connectToField": "_id",
    "as": "parent"
  ,
   "$project": 
    "name": 
      "$concat": [
        "$name",
         "$reduce": 
          "input": "$parent",
          "initialValue": "",
          "in":  "$concat": [",", "$$this.name", "$$value"] 
        
      ]
    
  
])

哪个会输出

[
  
    "_id": ObjectId("5ce4f84547e90a0b9c3c4763"),
    "name": "Test"
  ,
  
    "_id": ObjectId("5ce50caf09359e1b8ccf5c79"),
    "name": "Test sub 1,Test"
  ,
  
    "_id": ObjectId("5ce53977e46da33e6cfdd9d1"),
    "name": "Test Sub 2,Test sub 1,Test"
  
]

MongoPlayground

【讨论】:

以上是关于使用 mongodb 聚合获取父子关系的主要内容,如果未能解决你的问题,请参考以下文章

使用聚合和查找 mongodb 从对象数组中获取最小值

使用聚合和查找 mongodb 从对象数组中获取最小值

MongoDB聚合(aggregate)常用操作及示例

mongoDB表与表的关系及聚合管道查询

Maven项目构建基础知识

Maven项目构建基础知识