“如何通过mongodb聚合获得'父母与子女'关系”

时间:2019-05-29 10:38:21

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

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

收藏

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将为null。父级位置可以是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"
        }
    ]

1 个答案:

答案 0 :(得分:0)

我认为您不应该让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