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

Mik*_*e M 2 mongoose mongodb node.js

我有一个架构:

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

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

Project.aggregate([{$project:{topics:1}}]);
Run Code Online (Sandbox Code Playgroud)

但这给了我一系列带有主题字段的Project对象.我想要的是一个包含主题对象的数组.

我怎样才能做到这一点?

Bla*_*ven 6

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

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

    }
)
Run Code Online (Sandbox Code Playgroud)

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

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

});
Run Code Online (Sandbox Code Playgroud)

但那里等候一分钟,因为我知道你真的问这里.这不是_id您想要的值,但您的Topic数据上有一个属性,如"name".

由于您的项目是"引用"而在另一个集合中,因此您无法.distinct()对另一个集合中的文档属性执行聚合管道或操作.把基本"的MongoDB不执行联接"和猫鼬.populate()不是一个联接,只是一些"模拟",与另外的查询(IES).

但是你当然可以从"Project"中找到"distinct"值,然后从"Topic"中获取信息.如:

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

    });
});
Run Code Online (Sandbox Code Playgroud)

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