MongoDB $graphLookup 用于查找集合中相关文档的层次结构

问题描述 投票:0回答:1

我正在尝试使用 $graphLookup 和键 partOf 从 MongoDB 中的集合中查找文档的层次结构(聚合),并且包含其中存储类别数组和内部 _id 字段的对象数据类型。

输入集合示例(relationships_collection):

// Doc 1:

{
  "_id": "gotham_hotel",
  "category": "hotel",
  "partOf": {
    "street": [
      "kings_street_street"
    ]
}
// Doc 2:

{
  "_id": "kings_street_street",
  "category": "street",
  "partOf": {
    "pincode": [
      "m24ah_pincode"
    ]
  }
}
// Doc 3:

{
  "_id": "m24ah_pincode",
  "category": "pincode",
  "partOf": {
    "city": [
      "manchester_city"
    ]
  }
}
// Doc 4:

{
  "_id": "manchester_city",
  "category": "city",
  "partOf": {
    "country": [
      "england_country"
    ]
  }
}
// Doc 5:

{
  "_id": "england_country",
  "category": "country",
  "partOf": {
    "continent": [
      "europe_continent"
    ]
  }
}
// Doc 6:

{
  "_id": "europe_continent",
  "category": "continent",
  "partOf": {
    "region": [
      "north_region"
    ]
  }
}
// Doc 7 (Not partOf any other document _id. Dead End):

{
  "_id": "north_region",
  "category": "region",
  "contains": {
    "continent": [
      "europe_continent",
      "antarctica_continent"
    ]
  }
}

聚合的预期输出:

// Fetch complete hierarchy of gotham_hotel or any other document:

{
  "_id": "gotham_hotel",
  "category": "hotel",
  "partOf": {
    "street": [
      {
        "_id": "kings_street_street",
        "category": "street",
        "partOf": {
          "pincode": [
            {
              "_id": "m24ah_pincode",
              "category": "pincode",
              "partOf": {
                "city":  [
                  {
                    "_id": "manchester_city",
                    "category": "city",
                    "partOf": {
                      "country": [
                        {
                          "_id": "england_country",
                          "category": "country",
                          "partOf": {
                            "continent": [
                              {
                                "_id": "europe_continent",
                                "category": "continent",
                                "partOf": {
                                  "region": [
                                    {
                                      "_id": "north_region",
                                      "category": "region",
                                      "contains": {
                                        "continent": [
                                          "europe_continent",
                                          "antarctica_continent"
                                        ]
                                      }
                                    }
                                  ]
                                }
                              }
                            ]
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    ]
  }
}

我尝试使用以下聚合查询,但无法获得所需的输出。

[
  {
    $match: {
      _id: "gotham_hotel"
    }
  },
  {
    $graphLookup: {
      from: "relationships_collection",
      startWith: "$partOf.street",
      connectFromField: "partOf.street",
      connectToField: "_id",
      depthField: "depth",
      as: "partOfHierarchy"
    }
  },
  {
    "$set": {
      "partOf": {
        "street": {
          "$setUnion": [
            {
              "$ifNull": [
                "$partOf.steet",
                []
              ]
            },
            {
              "$reduce": {
                "input": "$partOfHierarchy.partOf.street",
                "initialValue": [],
                "in": {
                  "$setUnion": [
                    "$$value",
                    "$$this"
                  ]
                }
              }
            }
          ]
        },
        "pincode": {
          "$setUnion": [
            {
              $ifNull: [
                "$partOf.pincode",
                []
              ]
            },
            {
              "$reduce": {
                "input": "$partOfHierarchy.partOf.pincode",
                "initialValue": [],
                "in": {
                  "$setUnion": [
                    "$$value",
                    "$$this"
                  ]
                }
              }
            }
          ]
        }
      }
    }
  }
]

如何使用聚合查询获得所需的输出?

mongodb nosql
1个回答
0
投票

您无法从 MongoDB 获得精确的输出。

但是,在像这样的简单链表的情况下,您可以获得一个数组,该数组可以在客户端轻松转换为该层次结构。

首先,更改架构以简化查找。 由于每个 id 都已用其类型标记,因此可能不需要显式指定类型,但如果有的话,将其添加为同级字段会使这更容易。 比如:

      "partOf": [
        {
          "type": "street",
          "id": "kings_street_street"
        }

这简化了 graphLookup 阶段,因为所有文档的字段名称都是一致的:

  {"$graphLookup": {
      "from": "relationships_collection",
      "startWith": "$partOf.id",
      "connectFromField": "partOf.id",
      "connectToField": "_id",
      "as": "LookedUp",
      "depthField": "depth"
  }}

这会返回未排序数组中发现的文档,但是使用

depthField
,可以轻松排序:

{"$addFields": {
      "LookedUp": {
        "$sortArray": {
          "input": "$LookedUp",
          "sortBy": {"depth": 1}
        }
      }
}}

生成的数组包含层次结构,在客户端,您可以迭代该数组以将每个元素嵌套在其前面的元素中。

示例:游乐场

© www.soinside.com 2019 - 2024. All rights reserved.