【问题标题】:"How to get 'parent to child' relation with mongodb aggregation"“如何通过 mongodb 聚合获得‘父子’关系”
【发布时间】:2019-05-29 10:38:20
【问题描述】:

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

收藏

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("5cee1002a01ad50f5c222982"),
    "status" : "1",
    "name" : "Ground Floor",
    "settings" : {
        "zoom" : "0",
        "positionX" : "0",
        "positionY" : "0",
        "width" : "498",
        "height" : "498"
    },
    "image" : "1559105538977.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:52:18.999Z"),
    "createdAt" : ISODate("2019-05-29T04:52:18.999Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee103ca01ad50f5c222983"),
    "status" : "1",
    "name" : "Kitchen",
    "settings" : {
        "zoom" : "0",
        "positionX" : "0",
        "positionY" : "0",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":3,\"points\":[{\"x\":20,\"y\":178},{\"x\":19,\"y\":75},{\"x\":56,\"y\":71},{\"x\":57,\"y\":52},{\"x\":80,\"y\":18},{\"x\":138,\"y\":17},{\"x\":165,\"y\":52},{\"x\":165,\"y\":94},{\"x\":174,\"y\":96},{\"x\":173,\"y\":179}],\"fill\":\"rgba(178,40,40,0.58)\"}",
    "parentId" : ObjectId("5cee1002a01ad50f5c222982"),
    "image" : "1559105596975.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:53:16.990Z"),
    "createdAt" : ISODate("2019-05-29T04:53:16.990Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee1078a01ad50f5c222984"),
    "status" : "1",
    "name" : "Cbot",
    "settings" : {
        "zoom" : "0",
        "positionX" : "0",
        "positionY" : "0",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":3,\"points\":[{\"x\":20,\"y\":311},{\"x\":17,\"y\":59},{\"x\":84,\"y\":58},{\"x\":88,\"y\":312}],\"fill\":\"rgba(20,205,123,0.67)\"}",
    "parentId" : ObjectId("5cee103ca01ad50f5c222983"),
    "image" : "1559105656049.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:54:16.070Z"),
    "createdAt" : ISODate("2019-05-29T04:54:16.070Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee10c1a01ad50f5c222985"),
    "status" : "1",
    "name" : "Drower 1",
    "settings" : {
        "zoom" : "5",
        "positionX" : "470",
        "positionY" : "70",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":3,\"points\":[{\"x\":21,\"y\":102},{\"x\":81,\"y\":104},{\"x\":79,\"y\":43},{\"x\":21,\"y\":43}],\"fill\":\"rgba(16,77,193,0.5)\"}",
    "parentId" : ObjectId("5cee1078a01ad50f5c222984"),
    "image" : "1559105729881.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:55:29.901Z"),
    "createdAt" : ISODate("2019-05-29T04:55:29.901Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee110ea01ad50f5c222986"),
    "status" : "1",
    "name" : "Drawer 2",
    "settings" : {
        "zoom" : "5",
        "positionX" : "484",
        "positionY" : "103",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":1,\"coordinates\":{\"x\":23,\"y\":125,\"width\":58,\"height\":56},\"points\":[{\"x\":23,\"y\":125},{\"x\":81,\"y\":181}],\"fill\":\"rgba(117,37,109,0.74)\"}",
    "parentId" : ObjectId("5cee1078a01ad50f5c222984"),
    "image" : "1559105806551.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:56:46.574Z"),
    "createdAt" : ISODate("2019-05-29T04:56:46.574Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee1148a01ad50f5c222987"),
    "status" : "1",
    "name" : "Drawer 3",
    "settings" : {
        "zoom" : "5",
        "positionX" : "477",
        "positionY" : "94",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":3,\"points\":[{\"x\":22,\"y\":205},{\"x\":20,\"y\":290},{\"x\":84,\"y\":288},{\"x\":85,\"y\":205}],\"fill\":\"rgba(164,108,54,0.57)\"}",
    "parentId" : ObjectId("5cee1078a01ad50f5c222984"),
    "image" : "1559105864947.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:57:44.972Z"),
    "createdAt" : ISODate("2019-05-29T04:57:44.972Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee5e683b9f67a9f501f818"),
    "status" : "1",
    "name" : "Washroom",
    "settings" : {
        "zoom" : "5",
        "positionX" : "477",
        "positionY" : "94",
        "width" : "498",
        "height" : "498"
    },
    "area" : "{\"type\":3,\"points\":[{\"x\":22,\"y\":205},{\"x\":20,\"y\":290},{\"x\":84,\"y\":288},{\"x\":85,\"y\":205}],\"fill\":\"rgba(164,108,54,0.57)\"}",
    "parentId" : ObjectId("5cee1002a01ad50f5c222982"),
    "image" : "1559105864947.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:57:44.972Z"),
    "createdAt" : ISODate("2019-05-29T04:57:44.972Z"),
    "__v" : 0
},
{
    "_id" : ObjectId("5cee5f593b9f67a9f501fa01"),
    "status" : "1",
    "name" : "Third Floor",
    "settings" : {
        "zoom" : "0",
        "positionX" : "0",
        "positionY" : "0",
        "width" : "498",
        "height" : "498"
    },
    "image" : "1559105538977123.jpg",
    "businessId" : ObjectId("5cbd61dc3b56b902284ea388"),
    "locationColor" : [],
    "updatedAt" : ISODate("2019-05-29T04:52:18.999Z"),
    "createdAt" : ISODate("2019-05-29T04:52:18.999Z"),
    "__v" : 0
}]

JSON 格式的预期结果

[
        {
            "_id": "5cee1002a01ad50f5c222982",
            "name": "Ground Floor"
        },
        {
            "_id": "5cee103ca01ad50f5c222983",
            "name": "    Kitchen"
        },
        {
            "_id": "5cee1078a01ad50f5c222984",
            "name": "        Cbot"
        },
        {
            "_id": "5cee110ea01ad50f5c222986",
            "name": "            Drawer 2"
        },
        {
            "_id": "5cee1148a01ad50f5c222987",
            "name": "            Drawer 3"
        },
        {
            "_id": "5cee10c1a01ad50f5c222985",
            "name": "            Drower 1"
        },
        {
            "_id": "5cee5e683b9f67a9f501f818",
            "name": "    Washroom"
        },
        {
            "_id": "5cee5f593b9f67a9f501fa01",
            "name": "Third Floor"
        }
    ]

【问题讨论】:

    标签: node.js mongodb express mongoose aggregation-framework


    【解决方案1】:

    我认为您不应该让 mongodb 处理 name 格式。所以我的解决方案是找到某个name之前需要多少个空格,这样js就可以处理格式化了。这是查询:

    db.collection.aggregate([
        {
            $graphLookup: {
                from: "collection",
                startWith: "$parentId",
                connectFromField: "parentId",
                connectToField: "_id",
                as: "hierarchy"
            }
        },
        {
            $project: {
                "_id": 1,
                "name": 1,
                "hierarchy_size": { $size: "$hierarchy" }
            }
        }
    ]);
    

    使用$graphLookup,数据库正在构建内存中的connectFromFieldconnectToField 之间的边图。从图中你只需要层次结构的深度,所以我计算了hierarchy_size。这是输出:

    /* 1 */
    {
        "_id" : ObjectId("5cee1002a01ad50f5c222982"),
        "name" : "Ground Floor",
        "hierarchy_size" : 0
    }
    
    /* 2 */
    {
        "_id" : ObjectId("5cee103ca01ad50f5c222983"),
        "name" : "Kitchen",
        "hierarchy_size" : 1
    }
    
    /* 3 */
    {
        "_id" : ObjectId("5cee1078a01ad50f5c222984"),
        "name" : "Cbot",
        "hierarchy_size" : 2
    }
    
    /* 4 */
    {
        "_id" : ObjectId("5cee10c1a01ad50f5c222985"),
        "name" : "Drower 1",
        "hierarchy_size" : 3
    }
    
    /* 5 */
    {
        "_id" : ObjectId("5cee110ea01ad50f5c222986"),
        "name" : "Drawer 2",
        "hierarchy_size" : 3
    }
    
    /* 6 */
    {
        "_id" : ObjectId("5cee1148a01ad50f5c222987"),
        "name" : "Drawer 3",
        "hierarchy_size" : 3
    }
    
    /* 7 */
    {
        "_id" : ObjectId("5cee5e683b9f67a9f501f818"),
        "name" : "Washroom",
        "hierarchy_size" : 1
    }
    
    /* 8 */
    {
        "_id" : ObjectId("5cee5f593b9f67a9f501fa01"),
        "name" : "Third Floor",
        "hierarchy_size" : 0
    }
    

    这里唯一的问题可能是查询性能,但这取决于您需要处理多少数据。还要考虑memory limit

    【讨论】:

    • 感谢您的回答。你节省了我很多时间。
    猜你喜欢
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 2021-08-24
    • 2023-03-03
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多