$ filter与$ or,$ gte,$ lte运算符的嵌套级别

时间:2018-07-30 06:09:10

标签: mongodb nosql mongodb-query aggregation-framework nosql-aggregation

我想过滤MONGO db中的多个嵌套文档

示例JSON:

--allow-empty

}

预期输出:仅过滤具有available_qty <50和> 10的成员(不是全部)和members.product_warehouses.available_qty <50和> 20

查询:

{ 
"_id" : ObjectId("5b5c3afbcc43cb5ed64b7a04"), 
"id" : NumberLong(15015060), 
"name" : "1801_Conf", 
"type" : NumberInt(2), 
"members" : [
    {
        "id" : NumberLong(15015061), 
        "name" : "1801_Conf-W--", 
        "sku" : "1801_new", 
        "type" : NumberInt(1), 
        "parent_id" : NumberLong(15015060), 
        "available_qty" : NumberInt(10), 
        "on_hand_qty" : NumberInt(10), 
        "outgoing_qty" : NumberInt(0), 
        "incoming_qty" : NumberInt(0), 
        "shortage_qty" : NumberInt(0), 
        "product_warehouses" : [
            {
                "warehouse_id" : NumberLong(3), 
                "available_qty" : NumberInt(10), 
                "outgoing_qty" : NumberInt(0), 
                "incoming_qty" : NumberInt(0)
            },
            {
                "warehouse_id" : NumberLong(4), 
                "available_qty" : NumberInt(600), 
                "outgoing_qty" : NumberInt(0), 
                "incoming_qty" : NumberInt(0)
            }
        ], 
        ]
    } 
] 

错误::{“ ok”:0,“ errmsg”:“无效的运算符'$ elemMatch'”,“ code”:15999}:聚合失败

4 个答案:

答案 0 :(得分:1)

您需要首先$filtermembers数组,同时必须将$filter应用于product_warehouses数组,并循环遍历已过滤的{{1} }使用$map聚合的数组。

最后,您需要将members$and$gt$eq聚合运算符放在一起,这与您的预期输出条件相同

cond

给它一个try

答案 1 :(得分:1)

  

请尝试以下查询,它可以完美且经过正确测试

db.test.aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$members",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 2
    {
        $match: {
             $and: [ 

                   {"members.available_qty": {$gte:10}}, 
                   {"members.available_qty": {$lte:50}} 
                   ]
        }
    },

    // Stage 3
    {
        $project: {
            "_id" :1, 
            "id" :1, 
            "name" :1, 
            "type" :1, 
            "members" : {
                "id":1,
                "name" :1, 
                "sku" : 1, 
                "type" :1, 
                "parent_id" :1, 
                "available_qty" :1, 
                "on_hand_qty" :1, 
                "outgoing_qty" :1, 
                "incoming_qty" :1, 
                "shortage_qty" :1, 
                "product_warehouses": {
                            $filter: {
                                input: "$members.product_warehouses",
                                as: "item",
                                cond: {
                                  "$and": [
                                    { "$gte": [ "$$item.available_qty", 20] },
                                    { "$lte": [ "$$item.available_qty", 50 ] },
                                    ]
                                }
                            }
                        }

                },

        }
    },

    // Stage 4
    {
        $match: {
            "members.product_warehouses":{$ne: []}

        }
    },

    // Stage 5
    {
        $group: {
            _id:"$_id",
            "id" :{ $last: '$id' }, 
            "name" :{ $last: '$name' }, 
            "type" : { $last: '$type' }, 
            members: { $addToSet: "$members" }
        }
    },
],

);

答案 2 :(得分:1)

据我了解,这是您需要的查询。

db.col.aggregate([
    {"$unwind" : "$members"},
    {"$match" : {"$and" : [{"members.available_qty" : {"$lt" : 50}},{"members.available_qty" : {"$gt" : 10}}]}},
    {"$match" : {"$and" : [{"members.product_warehouses.available_qty" : {"$lt" : 50}},{"members.product_warehouses.available_qty" : {"$gt" : 20}}]}},
    {"$group" : {"_id" : "$_id",
        "type" : {"$first" : "$type"},
        "name" : {"$first" : "$name"},
        "id" : {"$first" : "$id"},
        "members" : {"$addToSet" : "$members"}
        }
    }
]);

db.lo.aggregate([
{"$unwind" : "$members"},
{"$match" : {
    "$and" : [
        {"members.available_qty" : {"$lt" : 50}},
        {"members.available_qty" : {"$gt" : 10}}
        ]
    }
},
{"$match" : { 
    "members.product_warehouses": { 
        "$elemMatch":{ 
            "available_qty": { "$lt": 50 }, 
            "available_qty": { "$gt": 20 }
        } 
    } 
}},
{"$group" : {"_id" : "$_id",
    "type" : {"$first" : "$type"},
    "name" : {"$first" : "$name"},
    "id" : {"$first" : "$id"},
    "members" : {"$addToSet" : "$members"}
    }
}

]);

如果任何一个子文档都符合以下条件 members.product_warehouses.available_qty> 20和members.product_warehouses.available_qty <50 ,它将返回整个product_warehouses数组,与 $ elemMatch

答案 3 :(得分:1)

您可以使用以下聚合查询。由于$elemMatch$project阶段不是有效的运算符,因此您可以用here$filter$size比较来代替该部分。

{"members":{
  "$filter":{
    "input":"$members",
    "cond":{
      "$and":[
        {"$gte":["$$this.available_qty",10]},
        {"$lte":["$$this.available_qty",50]},
        {"$gt":[
          {"$size":{
            "$filter":{
              "input":"$$this.product_warehouses",
              "cond":{
                "$and":[
                  {"$gte":["$$this.available_qty",20]},
                  {"$lte":["$$this.available_qty",50]}
                ]
              }
            }
          }},
          0
        ]}
      ]
    }
  }
}}