从数组中获得所有匹配属性的结果

我知道如何使MongoDB根据如下数组find一行:

useritems.find({userid: useridhere, "items.id": idhere}) 

但是,我将如何search,并获得所有被激活的项目,或获得所有项目的物业属性? 例如:

 useritems.find({userid: useridhere, "items.activated": true}) 

会导致从激活的用户获取所有项目是真实的。

这是我的项目架构:

 var userItemsSchema = new Schema({ userid : String, items: [ { id: {type: Number, default: 1}, activated: { type: Boolean, default: false}, endtime : {type: Number, default: 0}, }, ], }); module.exports = mongoose.model('useritems', userItemsSchema); 

你想在这里$filter

 useritems.aggregate([ { "$match": { "userid": ObjectId(useridhere), "items.activated": true }}, { "$addFields": { "items": { "$filter": { "input": "$items", "as": "i", "cond": "$$i.activated" } } }} ],(err,results) => { }); 

注意到在聚合框架中,诸如useridhere这样的值通常允许你传入一个“string”,并且会自动将这个string“自动加载”到你的ObjectId值中。 这在问题#1399的汇总框架中没有发生 ,只是因为它可能会改变所作用的文档的“形状”,所以不能应用“模式”。

所以你可能想要从核心驱动程序导入它:

 const ObjectId = require('mongodb').ObjectID; 

然后您可以手动“投射”这些值。

当然,如果这样的值实际上是从另一个mongoose对象而不是从req.params或类似的中获取的,那么它应该是一个ObjectIdtypes。

之所以使用.aggregate()是因为“标准投影”只能匹配一个元素。 即:

 useritems.find({ userid: useridhere, "items.activated": true }) .select('items.$') .exec((err,items) => { }); 

这里位置$操作符返回“匹配”元素,但只有“第一个”匹配。

所以,在你想要“多个”匹配的地方,你可以使用$filter来代替,这比早期版本的MongoDB更有效,它要求你首先$unwind数组。

$unwind操作符只能用于现代版本(任何通过MongoDB 2.4的版本),如果你真的想在一个数组中使用一个“数值”作为一个操作,比如$group ,那么这个数值被表示为一个“分组键”。 在其他情况下,它的使用通常是一个“巨大的性能问题”,除了直接跟随$lookup pipeline阶段,它有一个特殊的重要用例。

否则,尽可能避免。 改用$filter

注意: $addFieldsstream水线阶段允许您“覆盖”一个元素而不指定所有其他字段。 如果你的MongoDB不支持这个操作符,请改用$project并明确指定所有的字段。 即:

  { "$project": { "userid": 1, "items": { "$filter": { "input": "$items", "as": "i", "cond": "$$i.activated" } } }} 

这可能是一个很好的select使用aggregate如:

 useritems.aggregate( { $match: {"_id" : id}}, { $unwind: '$items'}, { $match: {'items.activated': true}}, { $group: {_id: '$_id', items: {$push: '$items'}}}) 

你可以在这个问题上得到更多的信息: 如何用MongoDB过滤子文档中的数组

$ elemMatch操作符用于查询embedded式文档中的值

根据上面提到的描述,作为解决scheme,请尝试在MongoDB shell中执行以下查找操作。

  db.useritems.find({ userid: "random user_id", items: { $elemMatch: { activated: true } } })