在MongoDB中聚合并展平数组字段

时间:2015-06-26 08:24:50

标签: node.js mongodb mongoose

我有一个架构:

var ProjectSchema = new Schema({
    name: {
        type: String,
        default: ''
    },
    topics: [{
        type: Schema.ObjectId,
        ref: 'Topic'
    }],
    user: {
        type: Schema.ObjectId,
        ref: 'User'
    }
});

我想要做的是获取一个包含所有项目所有主题的数组。我无法直接查询主题并获得完整列表,因为某些主题未分配,并且它们不会将引用保留回项目(出于避免双向引用的原因)。所以我需要查询Project并汇总一些方法。我正在做类似的事情:

Project.aggregate([{$project:{topics:1}}]);

但是这给了我一个带有主题字段的Project对象数组。我想要的是一个带主题对象的数组。

我该怎么做?

1 个答案:

答案 0 :(得分:6)

在处理数组时,您通常希望首先在数组成员上使用$unwind,然后使用$group来查找不同的条目:

Project.aggregate(
    [
        { "$unwind": "$topics" },
        { "$group": { "_id": "$topics._id" } }
    ],
    function(err,docs) {

    }
)

但是对于这种情况,使用.distinct()可能更简单,它将与上面相同,但只有一个结果数组而不是文档:

Project.distinct("topics._id",function(err,topics) {

});

但请等一下,因为我知道你在这里问真的。它不是您想要的_id值,但您的Topic数据上有一个属性,例如" name"。

由于您的商品是"引用"在另一个集合中,您不能对另一个集合中的文档属性执行聚合管道或.distinct()操作。基本上放#34; MongoDB不执行连接"而mongoose .populate() 一个加入,只是"模仿"带有其他查询的那些。

但你当然可以找到" distinct"来自"项目"的价值然后从"主题"中获取信息。如:

Project.distinct("topics._id",function(err,topics) {
    Topic.find({ "_id": { "$in": topics } },function(err,topics) {

    });
});

这很方便,因为.distinct()函数已经返回了一个适合与$in一起使用的数组。