Mongoose / MongoDB查找()$或/ $和$ elemMatch内?

我们目前有一个查询电影集合返回与用户生成的“编译”标题匹配的“编译”文档。

用户可以应用一些filter: 受众群体提供者格式

目前,即使匹配的“标题”不适合filter,而是“编译”中的第二部电影与filter匹配,此find()组合将返回以下文档。

{ "_id": "551781485d9d35e4720c9057", "name": "Consciousness", "audience": { "adults": true, "teenagers": true, "kids": false }, "compilation": [ { "title": "2001", "_id": "551781485d9d35e4720c9059", "provider": { "amazon": false, "apple": true, "hulu": false, "google": true, "xfinity": false }, "format": { "hd": false, "sd": false, "4k": true } }, { "title": "Matrix", "_id": "551781485d9d35e4720c9059", "provider": { "amazon": false, "apple": true, "hulu": false, "google": true, "xfinity": false }, "format": { "hd": true, "sd": false, "4k": false } } ] } 

这怎么可以重写,以便$或+ $和查询具体到$ elemMatch? 它适用于具有单个电影但不是多个电影的“编辑”。

 Models.Movies.find( { "collection": { "$elemMatch": { "title": "2001" } } } ) .and([ {$or : audienceQuery}, {$or : providerQuery} ]) .and(formatQuery) 

过滤查询如下所示:

 audienceQuery == {"audience.adults":true}, {"audience.teenagers":true}, {"audience.kids":false}; providerQuery == {"compilation.provider.apple":true}, {"compilation.provider.google":true}; formatQuery == {"compilation.format.hd":true}; 

考虑使用聚合框架 ,可以在stream水线阶段的开始阶段利用$match操作进行早期过滤,以限制进入stream水线的文档。 当放置在pipe道的开始处时, $match操作使用合适的索引来仅扫描集合中的匹配文档。 你的第二个stream水线阶段将涉及在compilation数组上使用$unwind操作,这样$match操作的后续应用程序将过滤解构的数组:剩余的stream水线操作$group$project然后沿着分组文档传递,只有来自之前过滤的input文档和新计算的字段的指定字段:

所以你的聚合pipe道看起来像这样:

 Models.Movies.aggregate([ { "$match": { "compilation.title": "2001", "$and": [ { "$or": [{"audience.adults": true}, {"audience.teenagers": true}, {"audience.kids": false}] }, { "$or": [{"compilation.provider.apple": true}, {"compilation.provider.google": true}] } ], "compilation.format.hd": true } }, { "$unwind": "$compilation" }, { "$match": { "compilation.title": "2001", "$and": [ { "$or": [{"audience.adults": true}, {"audience.teenagers": true}, {"audience.kids": false}] }, { "$or": [{"compilation.provider.apple": true}, {"compilation.provider.google": true}] } ], "compilation.format.hd": true } }, { "$group": { "_id": { "_id": "$_id", "name": "$name", "audience": "$audience" }, "compilation": { "$push": "$compilation" } } }, { "$project": { "_id": "$_id._id", "name": "$_id.name", "audience": "$_id.audience", "compilation": 1 } } ]) 

结果:

 /* 0 */ { "result" : [ { "_id" : "551781485d9d35e4720c9057", "compilation" : [ { "title" : "2001", "_id" : "551781485d9d35e4720c9059", "provider" : { "amazon" : false, "apple" : true, "hulu" : false, "google" : true, "xfinity" : false }, "format" : { "hd" : true, "sd" : false, "4k" : true } } ], "name" : "Consciousness", "audience" : { "adults" : true, "teenagers" : true, "kids" : false } } ], "ok" : 1 }