Mongodb,使用$ lookup进行聚合查询

时间:2016-10-07 07:42:56

标签: mongodb mongoose mongodb-query aggregation-framework

有两个收藏,标签和人物。

标签型号:

{
  en: String,
  sv: String
}

人模特:

{
  name: String,
  projects: [
    title: String,
    tags: [
      {
        type: Schema.ObjectId,
        ref: 'tag'
      }
    ]
  ]

}

我想查询返回人员模型中使用的所有标签。所有文件。

一样的Sometehing
var query = mongoose.model('tag').find({...});

或者我应该以某种方式使用聚合方法?

2 个答案:

答案 0 :(得分:29)

对于任何特定人员文档,您可以使用populate()功能,如

var query = mongoose.model("person").find({ "name": "foo" }).populate("projects.tags");

如果你想搜索任何有'MongoDB'或'Node JS'标签的人,你可以在populate()函数重载中包含查询选项:

var query = mongoose.model("person").find({ "name": "foo" }).populate({
    "path": "projects.tags",
    "match": { "en": { "$in": ["MongoDB", "Node JS"] } }
});

如果您希望所有人都在"project.tags"中存在所有标记,那么聚合框架就是您的选择。考虑在人员集合上运行此管道,并使用 $lookup 运算符在标记集合上执行左连接:

mongoose.model('person').aggregate([
    { "$unwind": "$projects" },
    { "$unwind": "$projects.tags" },
    {
        "$lookup": {
            "from": "tags",
            "localField": "projects.tags",
            "foreignField": "_id",
            "as": "resultingTagsArray"
        }
    },
    { "$unwind": "$resultingTagsArray" },
    {
        "$group": {
            "_id": null,
            "allTags": { "$addToSet": "$resultingTagsArray" },
            "count": { "$sum": 1 }
        }
    }
 ]).exec(function(err, results){
    console.log(results);
 })

对于任何特定的人,然后应用 $match 管道作为过滤文档的第一步:

mongoose.model('person').aggregate([
    { "$match": { "name": "foo" } },
    { "$unwind": "$projects" },
    { "$unwind": "$projects.tags" },
    {
        "$lookup": {
            "from": "tags",
            "localField": "projects.tags",
            "foreignField": "_id",
            "as": "resultingTagsArray"
        }
    },
    { "$unwind": "$resultingTagsArray" },
    {
        "$group": {
            "_id": null,
            "allTags": { "$addToSet": "$resultingTagsArray" },
            "count": { "$sum": 1 }
        }
    }
 ]).exec(function(err, results){
    console.log(results);
 })

如果您使用MongoDB版本> = 2.6或< = 3.0且不支持 $lookup 运算符,则另一种解决方法是将聚合中的结果填充为:

mongoose.model('person').aggregate([
    { "$unwind": "$projects" },
    { "$unwind": "$projects.tags" },    
    {
        "$group": {
            "_id": null,
            "allTags": { "$addToSet": "$projects.tags" }
        }
    }
 ], function(err, result) {
    mongoose.model('person')
    .populate(result, { "path": "allTags" }, function(err, results) {
        if (err) throw err;
        console.log(JSON.stringify(results, undefined, 4 ));
    });
});

答案 1 :(得分:1)

如果您使用的是MongoDb 3.2版,则可以使用执行左外连接的http://www.metatags.info/login