【问题标题】:Category hierarchy aggregation using mongodb and nodejs使用 mongodb 和 nodejs 的类别层次结构聚合
【发布时间】:2015-02-14 08:18:54
【问题描述】:

我的文档结构如下:

{
    "_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"
}

我正在使用 mongodb 和 nodejs 创建一个类别层次结构。

现在我想查询 _id = ‘54d81827e4a4449d023b4e34’ (Refridgerator) 并且应该取回所有子类别

如何在nodejs中实现以上功能?

另外,nodejs 对数据库使用异步调用,我无法获取带有父子关系的 json。

我将如何为此进行异步调用?

【问题讨论】:

  • 你到底尝试了什么,你到底是怎么失败的?
  • 为什么不使用:Collection.find({"parent":id})

标签: node.js mongodb hierarchy


【解决方案1】:

您想要冰箱和所有子类别?

而且异步也是个问题?

我认为你可以在这里使用聚合。

假设您正在寻找一个带有 _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]]
        }
    }
})

给定这个数据集:

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

我得到这个结果:

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

对于异步,通常你会这样做:

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

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

但这在一定程度上取决于您的 MongoDB 驱动程序。

即使你有更深的层次结构,你也可以扩展它。

【讨论】:

  • 我应该做哪些更改才能从集合中获取所有类别和子类别?
  • 可能会提出一个新问题,并非常准确地描述您拥有什么以及您想要什么。我认为它在这里不太合适,尤其是在 4 年过去之后。
  • 是的,你在写,但我有相同的文档结构,我想获得与父级相关的所有类别。你能帮忙吗?
  • @Zlatko 您建议的方式适用于最高级别 2 的类别。我需要获取父类别的所有子类别,其中子类别可以达到 4 级或 5 级。该怎么做?
【解决方案2】:

这与 NodeJS 无关,重要的是您的数据结构。

参考我对this question的回答,第一部分是关于如何高效实现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-08
    • 2013-03-15
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多