mongodb查询并返回文档数组中的特定元素,即使为null

时间:2015-05-27 16:28:29

标签: mongodb aggregation-framework

假设我在集合中包含这些文档:

 {_id: 1,fruit: apple,attributes: [{color: red,size: small,qty: 5},{color: green,size: small, qty 3}]},
 {_id: 2,fruit: mango,attributes: [{color: red,size: big, qty: 6},{color: green,size: small, qty: 7},{color: gold,size: medium, qty: 5},{color: yellow,size: small, qty: 20}]},
 {_id: 3,fruit: pineapple },
 {_id: 4,fruit: orange,attributes: [{color: orange,size: small,qty: 2}]}
  • 所有文件都会有字段"水果"
  • 某些文件可能没有"属性"阵列
  • 对于属性数组中包含元素的文档,可以是 介于1到20之间

我需要根据4到8之间的attributes.qty返回这个

  • 即使缺少属性字段或qty条件不匹配,也始终显示id和fruit
  • 在属性数组中最多只显示2个与搜索条件匹配的元素,按qty的降序排序

    {_ id:1,fruit:apple,attributes:[{color:red,size:small,qty:5}]},

    {_ id:2,水果:芒果,属性:[{color:green,size:small,qty:7},{color:red,size:big,qty:6}]},

    {_ id:3,水果:菠萝},

    {_ id:4,fruit:orange}

这是我正在使用的查询:

db.test.aggregate([
{"$unwind":"$attributes"},
{"$match":{"attributes.qty": {$gt:4, $lt:8}}},
{"$group":{"_id":"$_id","fruit":{$first:"$fruit"},"attributes":{$addToSet: "$attributes"}}}
])

我得到以下结果:

 {_id: 1,fruit: apple,attributes: [{color: red,size: small,qty: 5}]},
 {_id: 2,fruit: mango,attributes: [{color: red,size: big, qty: 6},{color: green,size: small, qty: 7},{color: gold,size: medium, qty: 5}]}

这没有菠萝和橙色记录;芒果属性中的值未排序,不限于2

请帮忙

更新

尝试使用$ redact。仍然没有接近获得理想的输出。使用$和,没有输出

db.test.aggregate([
{$match:{"site":{$exists:true}}},
        { "$redact": {
        "$cond": {
            "if": {
                $and:[ 
                {"$gt": ["$qty",4]},
                {"$lt": ["$qty,8]}
                ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])

1 个答案:

答案 0 :(得分:0)

此查询应该为您提供接近您想要的结果。

db.test.aggregate([
    { 
        "$redact": {
            "$cond": {
                "if": { $or : [ {$and:[ {"$gt": ["$qty",4]},{"$lt": ["$qty",8]}]}, { $not : "$qty" }]},
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }
    },
    {
        '$project': {
            'fruit': 1,
            'attributes' : {
                "$cond" : [{'$and': [ {$ne : ["$attributes", []]},{"$ifNull": ["$attributes", false] }]},"$attributes", [{ 'qty':'test'}] ]
            }
        }
    },
    {'$unwind': '$attributes'},
    {'$sort': {'attributes.qty': -1}},
    {'$group': {'_id': '$_id' , 'fruit' : {'$first': '$fruit'},'attributes': {'$push' : '$attributes'}}},
    {
        "$redact": {
            "$cond": {
                "if": { '$ne': ['$qty','test']},
                "then": "$$DESCEND",
                "else": "$$PRUNE"
            }
        }
    },
])

请注意{$not:"$qty"}是必要的,因为它也会扫描顶层文档,如果$redact在顶层找不到qty字段,则返回false,可能会删除整个文档我们不想要的。

结果:

{
    "result" : [ 
        {
            "_id" : ObjectId("5568335b52cdca6ba1c290f0"),
            "fruit" : "apple",
            "attributes" : [ 
                {
                    "color" : "red",
                    "size" : "small",
                    "qty" : 5
                }
            ]
        }, 
        {
            "_id" : ObjectId("5568335b52cdca6ba1c290f1"),
            "fruit" : "mango",
            "attributes" : [ 
                {
                    "color" : "green",
                    "size" : "small",
                    "qty" : 7
                }, 
                {
                    "color" : "red",
                    "size" : "big",
                    "qty" : 6
                }, 
                {
                    "color" : "gold",
                    "size" : "medium",
                    "qty" : 5
                }
            ]
        }, 
        {
            "_id" : ObjectId("5568335b52cdca6ba1c290f3"),
            "fruit" : "orange",
            "attributes" : []
        }, 
        {
            "_id" : ObjectId("5568335b52cdca6ba1c290f2"),
            "fruit" : "pineapple",
            "attributes" : []
        }
    ],
    "ok" : 1
}

不幸的是(在MongoDB 3.0中)聚合管道没有等效的$ slice。在MongoDB问题跟踪器中进行upvote / watch的相关功能请求是SERVER-6074: Allow $slice operator in $project

因此,您需要一种解决方法来获取最多2个文档。

  • 在您的应用程序代码中处理结果。
  • 使用Map/Reduce
  • 实施聚合