我正在尝试使用 $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 获得精确的输出。
但是,在像这样的简单链表的情况下,您可以获得一个数组,该数组可以在客户端轻松转换为该层次结构。
首先,更改架构以简化查找。 由于每个 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}
}
}
}}
生成的数组包含层次结构,在客户端,您可以迭代该数组以将每个元素嵌套在其前面的元素中。
示例:游乐场