Mongo-Array查询,只查找所有元素匹配的地方


Mongo - Array query, only find where all elements match

我正在尝试创建一个mongo查询,它将返回所有数组都有一个特定元素设置为false的结果。

数据记录示例:-

images: [
    {
        id: ObjectId("516bef7fc05e877b31000000"),
        primary: true
    },
    {
        id: ObjectId("516bef2ac05e879622000000"),
        primary: false
    },
    {
        id: ObjectId("516beeb7c05e879e2a000000"),
        primary: false
    }
],
name: "test",
etc: "etc"

我只想找到所有主字段都设置为false的文档,但通常(不使用查询选择器或elematch)mongo会返回此文档,因为至少有1个数组元素匹配。

如何让mongo只返回与我的搜索参数匹配的文档?

非常感谢。

使用聚合框架可以很容易地做到这一点:

db.so.aggregate( [
    { $unwind: "$images" },
    { $group: { 
        _id: '$_id', 
        all: { $sum: 1 },
        all_primary: { $sum: { $cond: [ { $eq: [ '$images.primary', true ] }, 1, 0 ] } },
        images: { $push: '$images' },
        name: { $first: '$name' },
        etc: { $first: '$etc' },
    } },
    { $project: {
        _id: 1,
        images: 1,
        name: 1,
        etc: 1,
        same: { $cond: [ { $eq: [ '$all', '$all_primary' ] }, 1, 0 ] }
    } },
    { $match: { 'same' : 1 } } 
] );

以此作为输入:

{
    "_id" : ObjectId("5203730bf8eaa52a846ebc3e"),
    "images" : [
        {
            "id" : ObjectId("516bef7fc05e877b31000000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516bef2ac05e879622010000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516beeb7c05e879e2a000010"),
            "primary" : true
        }
    ],
    "name" : "Derick",
    "Etc" : true
}
{
    "_id" : ObjectId("52037315f8eaa52a846ebc3f"),
    "images" : [
        {
            "id" : ObjectId("516bef7fc05e877b31000000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516bef2ac05e879622010000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516beeb7c05e879e2a000020"),
            "primary" : false
        }
    ],
    "name" : "James",
    "Etc" : true
}
{
    "_id" : ObjectId("520373621a78238235b6ffbf"),
    "images" : [
        {
            "id" : ObjectId("516bef7fc05e877b31000000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516bef2ac05e879622010000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516beeb7c05e879e2a000020"),
            "primary" : false
        }
    ],
    "name" : "James",
    "etc" : true
}
{
    "_id" : ObjectId("5203736b1a78238235b6ffc0"),
    "images" : [
        {
            "id" : ObjectId("516bef7fc05e877b31000000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516bef2ac05e879622010000"),
            "primary" : true
        },
        {
            "id" : ObjectId("516beeb7c05e879e2a000020"),
            "primary" : true
        }
    ],
    "name" : "James",
    "etc" : true
}

该输出:

{
    "result" : [
        {
            "_id" : ObjectId("5203736b1a78238235b6ffc0"),
            "images" : [
                {
                    "id" : ObjectId("516bef7fc05e877b31000000"),
                    "primary" : true
                },
                {
                    "id" : ObjectId("516bef2ac05e879622010000"),
                    "primary" : true
                },
                {
                    "id" : ObjectId("516beeb7c05e879e2a000020"),
                    "primary" : true
                }
            ],
            "name" : "James",
            "etc" : true,
            "same" : 1
        },
        {
            "_id" : ObjectId("5203730bf8eaa52a846ebc3e"),
            "images" : [
                {
                    "id" : ObjectId("516bef7fc05e877b31000000"),
                    "primary" : true
                },
                {
                    "id" : ObjectId("516bef2ac05e879622010000"),
                    "primary" : true
                },
                {
                    "id" : ObjectId("516beeb7c05e879e2a000010"),
                    "primary" : true
                }
            ],
            "name" : "Derick",
            "etc" : null,
            "same" : 1
        }
    ],
    "ok" : 1
}

排除images具有primary:true元素的所有文档不是更简单吗?

{ "images" : 
 { "$not" : 
  {"$elemMatch" : { "primary" : true }}
 }
}

当然,这只适用于布尔嵌套字段,如本例所示。

遇到类似查询的排序问题。。。但只要看看Dericks代码,文档就说不要在$group操作中使用$first,除非$group操作紧接在$sort之后。

http://docs.mongodb.org/manual/reference/operator/aggregation/first/#grp._S_first

假设图像是一个可以使用的文档(来自shell):

db.images.find({"primary":"false"})

如果图像是一个对象:

db.mydoc.find({'图像':{'主要':'false'}})