如何检索与mongodb中给定值完全匹配的文档

时间:2016-10-14 11:38:04

标签: mongodb

来自mongodb官方文档的

以下示例使用以下文档查询库存集合:

{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

以下示例查询清单集合以选择其中tags数组完全等于指定数组的所有文档,或者tags数组包含一个等于数组的元素[" A"," B&# 34; ]

db.inventory.find( { tags: { $eq: [ "A", "B" ] } } )

该查询相当于:

db.inventory.find( { tags: [ "A", "B" ] } )

两个查询都符合以下文档:

{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

现在我想知道如何查询以使文件的标签字段完全等于[ "A", "B" ]而不单独包含它或其他元素?我希望上面例子的结果只是返回的第一个文件:

{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }

1 个答案:

答案 0 :(得分:0)

如果您只想提取与您提供的数组完全匹配的文档,可以在查询中添加$size操作数:

db.inventory.find({
    $and: [
        { tags: "A" },
        { tags: "B" },
        { tags: { $size: 2 }}
    ]
});

上述查询仅匹配tags字段等于指定数组的文档,其元素按照确切的顺序排列。

评论中 chridam 提供的解决方案是一个更优雅的解决方案:

db.inventory.find({ "tags": { "$all": [ "A", "B" ], "$size": 2 } })

<强>更新

我插入了您在本地MongoDB实例中提供的文档来测试我的 chridam的查询,并且它们都从您提供的文档中返回相同的结果集:

{ "_id" : ObjectId("580146168ff3eea72fd1edc7"), "item" : { "name" : "ij", "code" : "456" }, "qty" : 25, "tags" : [ "A", "B" ] }
{ "_id" : ObjectId("580146168ff3eea72fd1edc8"), "item" : { "name" : "xy", "code" : "456" }, "qty" : 30, "tags" : [ "B", "A" ] }

正如您所看到的,它匹配数组的元素和大小,但它没有考虑它们在数组中出现的顺序。

因此,我探索了不同的方法,以便为您指定的结果提供工作解决方案,即匹配数组的确切内容及其顺序。

我设法使用$where运算符编写以下查询,该运算符符合您的请求:

db.items.find({ $where: function() {
    var arr = ["A", "B"],
        tags = this.tags;

    if(tags.length !== arr.length) {
        return false;
    }

    for(var i = 0; i < tags.length; i++) {
        if(tags[i] !== arr[i]) {
            return false;
        }
    }

    return true;
}});

/*
 * RESULT SET
 */
{ "_id" : ObjectId("580146168ff3eea72fd1edc7"), "item" : { "name" : "ij", "code" : "456" }, "qty" : 25, "tags" : [ "A", "B" ] }