如何使用mongoose在mongo中的对象数组中搜索两个单独的键

时间:2015-07-25 21:18:25

标签: mongodb mongoose

我需要能够使用用户ID的集合中的所有文档来管理文档子数组中的任何评论ID。

这是架构:

var postSchema = mongoose.Schema({
    user_id             : String,
    users_full_name     : String,
    username            : String,
    start_time          : String,
    post                : String,
    comments            : [{
        user_id         : String,
        start_time      : Date,
        comment         : String,
        cancelled       : Boolean,
        cancelled_time  : Date
    }]
});

当数组中只有一个doc时,这很好用:

modelPost.find({
    "comment.user_id": user_id,
    "comment.cancelled": {$ne:true}
}).sort({"post.start_time": -1}).find(function( err, posts ){
    if( err ){
        console.log( err );
    }

    return callback( posts );
});

但是只要我在comments数组中放入另一个对象,查询就不会返回任何内容。

当我删除"comment.cancelled": {$ne:true}位时,它确实有效。但我需要这一点......

评论对象中可以包含3个对象,但是其中两个可以属于一个用户,其中一个被取消,例如:

user_id             : 123,
users_full_name     : 'Bob Smith',
username            : 'bob.smith',
start_time          : some date,
post                : 'some very interesting post on something cool',
comments            : [{
    user_id         : 654,
    start_time      : some date,
    comment         : 'a nice comment',
    cancelled       : true,
    cancelled_time  : some time,
},{
    user_id         : 654,
    start_time      : some date,
    comment         : 'a nice comment'
},{
    user_id         : 701,
    start_time      : some date,
    comment         : 'a nice comment',
    cancelled       : true,
    cancelled_time  : some time,
},{
    user_id         : 888,
    start_time      : some date,
    comment         : 'another nice comment'
}]      

当文档像这样填充时,上述查询不会产生任何结果。当我使用"comment.cancelled": {$ne:true}时,它返回属于给定用户ID的所有注释,包括具有cancel = true的注释。

好像"comment.cancelled": {$ne:true}正在对整个数组进行交叉引用,它在数组中的对象上找到了comment.cancelled = true,因此不会返回整个帖子文档。

使用上面的示例,如果查询中的用户ID是654,则查询将返回完整的帖子。但是,如果查询中的id为701,则不会返回任何结果。和obv。 888将返回帖子。

目前我必须进行帖子查询操作以过滤结果。在' 701'场景。

1 个答案:

答案 0 :(得分:3)

为了匹配数组元素的多个条件和属性,您需要$elemMatch运算符。这确保了"两者"条件满足"相同"数组元素:

modelPost.find({ 
  "comments": { 
    "$elemMatch": {
        "user_id": user_id,
        "cancelled": { "$exists": false }
    }
  }
}.sort({"post.start_time": -1}).exec(function( err, posts ){

})

同样正确的方式来匹配你的"取消" "可能不存在的属性使用$exists

没有$elemMatch,所有"点符号"这里的形式确实在于确认这些条件是否满足了某些条件。数组的元素,意味着数组中的元素具有必需的" user_id"并且没有"取消"属性。由于至少有一个数组元素被取消"这不是一个条件。

$elemMatch视为自己的查询,应用于"每个"数组元素的数量,以测试其中包含的条件是否为真。对于你的逻辑" AND"操作,然后"两者"需要在同一个数组元素上满足条件,在适用的情况下正确返回true。

另请注意"排序"在数组时间属性上只应用于"最大值"数组中的(降序)并且是排序文档而不是数组条目。如果您希望结果是"排序"通过与您的条件匹配的数组元素,您需要使用aggregation framework来解决此问题,但这是另一个问题