简体   繁体   English

使用MongoDB和Node.js进行类别层次结构聚合

[英]Category hierarchy aggregation using mongodb and nodejs

My document structure is as follows: 我的文档结构如下:

{
    "_id" : ObjectId("54d81827e4a4449d023b4e34"),
    "cat_id" : 1,
    "description" : "Refridgerator",
    "image" : "refridgerator",
    "parent" : null,
    "slug" : "refridgerator"
}
{
    "_id" : ObjectId("54dc38bce4a4449d023b4e58"),
    "name" : "Ice Cream",
    "description" : "Ice Cream",
    "image" : "ice-cream.jpg",
    "slug" : "ice-cream",
    "parent" : "54d81827e4a4449d023b4e34"
}
{
    "_id" : ObjectId("54dc3705e4a4449d023b4e56"),
    "name" : "Chocolate",
    "description" : "Chocolate",
    "image" : "chocolate.jpg",
    "slug" : "chocolate",
    "parent" : "54d81827e4a4449d023b4e34"
}

I'm making a category hierarchy using mongodb and nodejs. 我正在使用mongodb和nodejs创建类别层次结构。

Now I wish to query for _id = '54d81827e4a4449d023b4e34' (Refridgerator) and should get back all the child categories 现在我想查询_id = '54d81827e4a4449d023b4e34' (Refridgerator),并且应该获取所有子类别

How to achieve the above in nodejs? 如何在nodejs中实现以上?

Also, nodejs uses async call to the database, I'm unable to get the json structured with parent – child relations. 另外,nodejs使用对数据库的异步调用,我无法获得具有父子关系的json结构。

How would I do the async call for this? 我将如何对此进行异步调用?

This has nothing to do with NodeJS, it's your data structure that matters. 这与NodeJS无关,重要的是您的数据结构。

refer to my answer to this question , the first part is about how to implement it efficiently. 请参阅我对这个问题的回答 ,第一部分是关于如何有效地实施它。

You want the refridgerator and all the subcategories? 您想要冰箱和所有子类别吗?

And async is also a problem? 而且异步也是个问题吗?

I think you can use aggregation here. 我认为您可以在此处使用聚合。

Say you're looking for a category with _id variable which is an ObjectId of what you want, and it's subcategories. 假设您正在寻找带有_id变量的类别,该类别是所需的ObjectId,它是子类别。

db.yourCollection.aggregate({
    // get stuff where you have the parent or subcats.
    $match: {
         $or: [
               {_id: ObjectId("54de8b9f022ff38bbf5e0530")},
               {parent: ObjectId("54de8b9f022ff38bbf5e0530")}
              ]
         }
},
// reshape the data you'll need further on from each mached doc
{
    $project: {
        _id: false,
        data: {
            id: '$_id',
            name: '$name'
            // I guess you'll also want the `slug` and `image` here.
            // but that's homework :)
        },
        parent: '$parent'
    }
},
// now put a common _id so you can group them, and also put stuff into arrays
{
    $project: {
        id: {$literal: 'id'},
        mainCategory: {
            // if our parent is null, put our data.
            // otherwise put null here.
            $cond: [{$eq: [null, '$parent']}, {_id: '$data.id', name: '$data.name'}, undefined]
        },
        subcat: {
            // here is the other way around.
            $cond: [{$ne: [null, '$parent']}, {_id: '$data.id', name: '$data.name'}, null]

        }
    }
    // that stage produces for each doc either a mainCat or subcat
    // (and the other prop equals to null)
},
// finally, group the things so you can have them together
{
    $group: {
        _id: '$id',
        // a bit hacky, but mongo will yield to it
        mainCategory: {$max: '$mainCategory'},
        subCategories: {
            // this will, unfortunately, also add the `null` we have
            // assigned to main category up there
            $addToSet: '$subcat'
        }
    }
},
// so we get rid of the unwanted _id = 'id' and the null from subcats.
{
    $project: {
        _id: false,
        mainCategory: 1,
        subCategories: {
            $setDifference: ['$subCategories', [null]]
        }
    }
})

Given this data set: 给定此数据集:

[{
    "_id" : ObjectId("54de8b9f022ff38bbf5e0530"),
    "name" : "Fridge",
    "parent" : null
},
{
    "_id" : ObjectId("54de8bba022ff38bbf5e0531"),
    "name" : "choco",
    "parent" : ObjectId("54de8b9f022ff38bbf5e0530")
},
{
    "_id" : ObjectId("54de8bc8022ff38bbf5e0532"),
    "name" : "apple",
    "parent" : ObjectId("54de8b9f022ff38bbf5e0530")
}

I get this result: 我得到这个结果:

{
    "result" : [ 
        {
            "mainCategory" : {
                "_id" : ObjectId("54de8b9f022ff38bbf5e0530"),
                "name" : "Fridge"
            },
            "subCategories" : [ 
                {
                    "_id" : ObjectId("54de8bc8022ff38bbf5e0532"),
                    "name" : "apple"
                }, 
                {
                    "_id" : ObjectId("54de8bba022ff38bbf5e0531"),
                    "name" : "choco"
                }
            ]
        }
    ],
    "ok" : 1
}

As for async, typically you'd do something like this: 至于异步,通常您会执行以下操作:

db.collection.aggregate(thePipeLineAbove, function(err, results) {

    // handle err
    if (err) {
       // deal with it
    } else {
        console.log(results);
    }
});

But that depends a bit on your MongoDB driver. 但这取决于您的MongoDB驱动程序。

You could expand this even if you have deeper hierarchy structure. 即使您具有更深的层次结构,也可以扩展它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM