«Как получить отношение« родитель - ребенок »с агрегацией mongodb» - PullRequest
1 голос
/ 29 мая 2019

У меня есть одна коллекция под названием "местоположение".в этой коллекции все дочерние и родительские коллекции являются магазинами.Теперь я хочу создать запрос, который возвращает мне родительскую строку, разделенную дочерними пробелами.

Коллекция

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"
        }
    ]

1 Ответ

0 голосов
/ 29 мая 2019

Я не думаю, что вы должны позволить 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 БД строит в памяти граф ребер между connectFromField и connectToField. Из графика вам нужна только глубина вашей иерархии, поэтому я вычислил 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
}

Единственной проблемой здесь может быть выполнение запросов, но это зависит от того, сколько данных вам нужно обработать. Также учитывайте ограничение памяти .

...