Mongodb使用切片和元素匹配

时间:2016-12-28 00:17:46

标签: mongodb

我正在尝试在mongo db中检索数组中的元素。我想检索15个与模式不匹配的第一个元素

所以让我们想象一下

{
"_id" : ObjectId("s4dcsd5s4d6c54s6d"),
"items" : [
    {
        type : "TYPE_1",
        text : "blablabla"
    },
    {
        type : "TYPE_2",
        text : "blablabla"
    },
    {
        type : "TYPE_3",
        text : "blablabla"
    },
    {
        type : "TYPE_1",
        text : "blablabla"
    },
    {
        type : "TYPE_2",
        text : "blablabla"
    },
    {
        type : "TYPE_1",
        text : "blablabla"
    }
]
}

所以目前我有更多要匹配的元素与不匹配的元素相比,这就是我使用nin的原因。但它是为了简化

如果我使用

db.history.find({ "_id" : ObjectId("s4dcsd5s4d6c54s6d")}, { "items" : { "$elemMatch" : { "type" : { "$nin" : [ "TYPE_2" , "TYPE_3"]}}}, "items" : { $slice : [0, 2]}}).pretty()

似乎没有考虑元素匹配(如果我在切片后放置元素匹配则反向)

然后,如果我这样做:

db.history.find({ "_id" : ObjectId("s4dcsd5s4d6c54s6d")}, { "items" : { "$elemMatch" : { "type" : { "$nin" : [ "TYPE_2" , "TYPE_3"]}}, $slice : [0, 2]}}).pretty()

mongo抛出错误

你知道我该怎么做吗?

非常感谢

2 个答案:

答案 0 :(得分:2)

您需要使用聚合来限制您拥有的表单中的数组。使用$ filter应用条件和$ slice来限制数组元素。

db.history.aggregate([{
    $match: {
        _id: ObjectId("586309d6772c68234445f2a5")
    }
}, {
    "$project": {
        "items": {
            "$slice": [{
                    "$filter": {
                        "input": "$items",
                        "as": "item",
                        "cond": {
                            "$and": [{
                                $ne: ["$$item.type", "TYPE_2"]
                            }, {
                                $ne: ["$$item.type", "TYPE_3"]
                            }]
                        }
                    }
                },
                2
            ]
        }
    }
}])

示例输出:

{ "_id" : ObjectId("586309d6772c68234445f2a5"), "items" : [ { "type" : "TYPE_1", "text" : "blablabla" }, { "type" : "TYPE_1", "text" : "blablabla" } ] }

答案 1 :(得分:1)

您不能在案件中使用$elemMatch,因为它只会返回第一个元素。来自documentation

  

$ elemMatch $ elemMatch运算符限制了a的内容   查询结果中的字段仅包含第一个元素   匹配$ elemMatch条件。

您可以执行聚合查询,该查询将执行以下操作:

  • 与您的_id
  • 相匹配
  • 展开您的items数组,使数组中的每个项目都有一条记录
  • 匹配数组$nin
  • 的类型[ "TYPE_2" , "TYPE_3"]
  • 限制结果数

查询是:

db.history.aggregate([{
        $match: {
            _id: ObjectId("s4dcsd5s4d6c54s6d")
        }
    }, {
        $unwind: '$items'
    }, {
        $match: {
            'items.type': { '$nin': ["TYPE_2", "TYPE_3"] }
        }
    },
    { $limit: 2 }
])

它给出了:

{ "_id" : "s4dcsd5s4d6c54s6d", "items" : { "type" : "TYPE_1", "text" : "blablabla" } }
{ "_id" : "s4dcsd5s4d6c54s6d", "items" : { "type" : "TYPE_1", "text" : "blablabla" } }