从匹配属性

时间:2017-07-17 22:01:16

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我知道如何让MongoDB根据这样的数组找到一行:

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

但是,我将如何搜索并获取所有已激活的项目,或者根据items属性获取所有项目? 例如:

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);

3 个答案:

答案 0 :(得分:3)

你想要$filter

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

});

注意到聚合框架的值为useridhere,mongoose通常允许您传入“字符串”,并将该字符串“自动”转换为ObjectId值。 This does not happen in the aggregation frameworkIssue#1399,因为它可能会改变所采取行动的文件的“形状”,因此不能应用“架构”。

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

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

然后你可以手动“施放”这些值。

当然,如果这个值实际上是从另一个猫鼬对象而不是req.params或类似对象中检索到的,那么它应该是ObjectId类型。

为此使用.aggregate()的原因是“标准投影”仅匹配一个元素。即:

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

 });

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

因此,您希望“多个”匹配使用$filter,而这比早期版本的MongoDB更有效,它需要您首先$unwind数组。

$unwind运算符应该在现代版本中使用(通过MongoDB 2.4的任何内容),如果您确实想要在数组中使用“值”进行操作例如$group,其中该值表示为“分组键”。它在其他情况下的使用通常是一个“巨大的性能问题”,除了直接遵循$lookup管道阶段,它确实有一个特殊的重要用例。

否则最好避免。请改用$filter

  

注意: $addFields管道阶段允许您“覆盖”单个元素而不指定所有其他字段。如果您的MongoDB不支持此运算符,请改用$project并明确指定所有字段。即:

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

答案 1 :(得分:1)

使用aggregate可能是一个不错的选择:

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

您可以在此问题中获得更多信息:How to filter array in subdocument with MongoDB

答案 2 :(得分:-1)

$ elemMatch 运算符用于查询嵌入文档中的值

根据上述问题中的描述,作为解决方案,请尝试在MongoDB shell中执行以下查找操作。

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