如何聚合两个集合,其中一个集合中的字段大于另一个集合中的字段

时间:2017-02-22 06:28:46

标签: python mongodb mongodb-query aggregation-framework robo3t

我有两个集合,我们称之为集合A和集合B,它们都有价格字段和项目编号。所以我们说每个都有两个项目:

收藏A:

  

name = item1,price = 30

     

name = item2,price = 20

收集B:

  

name = item1,price = 50

     

name = item2,price = 10

我想显示收藏品A的价格大于收藏品B的价格的商品。对于上面的例子,例如item2。

我该如何撰写这样的查询?我正在使用robomongo。

(编辑)

跟进我之前的问题;

我想显示集合A的价格大于集合B的价格*(汇率)+(某些常数)

的项目

让我们说条件是;

  

其中A的价格> B的价格* 1.5 + 4

所以在这种情况下它应该仍然显示相同的项目。

让我们说条件是;

  

其中A的价格> B的价格* 1.5 + 10

然后它不应该显示任何项目

1 个答案:

答案 0 :(得分:1)

您可以使用 $lookup 运算符首先从collectionBcollectionA进行联接,将结果返回的单个元素数组展平为 $unwind ,然后使用 $redact 管道进行文档级别的编辑,其中包含文档 使用 $$KEEP 系统变量保留与指定条件匹配的内容,使用 $$PRUNE 放弃那些不满足条件的内容。最后,您需要运行以下聚合管道:

var exchangeRate = 1.5;
db.collectionA.aggregate([
    { "$match": { "price": { "$exists": true }, "name": { "$exists": true } } },
    {
        "$lookup": {
            "from": "collectionB",
            "localField": "name",
            "foreignField": "name",
            "as": "collectionB"
        }
    },
    { "$unwind": "$collectionB" },
    {
        "$redact": {
            "$cond": [
                { 
                    "$gt": [
                        "$price", {
                            "$add": [
                                { "$multiply": [ "$collectionB.price", exchangeRate ] },
                                4
                            ]
                        }
                    ]
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

Robomongo Demo

填充测试集合:

db.collectionA.insert([
    { "name": "item1", "price": 30 },
    { "name": "item2", "price": 20 }    
])

db.collectionB.insert([
    { "name": "item1", "price": 50 },
    { "name": "item2", "price": 10 }    
])

enter image description here

运行和调试聚合管道 enter image description here

示例输出:

{
    "_id" : ObjectId("58ad50a429b2961777f91c95"),
    "name" : "item2",
    "price" : 20,
    "collectionB" : {
        "_id" : ObjectId("58ad50a429b2961777f91c97"),
        "name" : "item2",
        "price" : 10
    }
}