2

I have two collections lets call them collection A and collection B and they both have a price field and item number. so lets say there are 2 items in each:

Collection A:

name = item1 , price = 30

name = item2 , price = 20

Collection B:

name = item1 , price = 50

name = item2 , price = 10

I want to display the items for which collection A's price is bigger than collection B's price. For the above example that would be item2 for instance.

How can I write such a query? I'm using robomongo.

(EDIT)

Follow up on my previous question;

I want to display the items for which collection A's price is bigger than collection B's price * (exchange rate) + (some constant)

Let's say condition is;

where A's price > B's price*1.5+4

so in this case it should still display the same item.

Let's say condition is;

where A's price > B's price*1.5+10

then it shouldn't display any of the items

Can Gokalp
  • 115
  • 1
  • 14

1 Answers1

1

You could use the $lookup operator to first do a join on collectionB from collectionA, flatten the single element array returned from the result with $unwind and then use $redact pipeline to do document level redaction where documents that match the specified condition are retained using the $$KEEP system variable, and those that do not satisfy the condition are discarded using $$PRUNE. In the end, you would need to run the following aggregate pipeline:

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

Populate test collections:

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

Run and debug aggregate pipeline: enter image description here

Sample Output:

{
    "_id" : ObjectId("58ad50a429b2961777f91c95"),
    "name" : "item2",
    "price" : 20,
    "collectionB" : {
        "_id" : ObjectId("58ad50a429b2961777f91c97"),
        "name" : "item2",
        "price" : 10
    }
}
chridam
  • 100,957
  • 23
  • 236
  • 235
  • Thank you very much for your very detailed and awesome answer!! Just to follow up on this; what if the price on the second collection is in other currency and I wanna compare item1 price (in collection A) vs item1 price*(the exchange rate) (lets say 1.5) in collection B. How can I incorporate this logic? Or if i wanna add buffer lets say I wanna get the items where item1 price in A greater than item1 (price + 10 )in B. I tried adding + this to your code but that didn't work – Can Gokalp Feb 22 '17 at 19:11
  • since exchange rate changes I don't want to update the collection B prices with 1.5.Lets say tomorrow the rate will be 1.6 and I'd wanna see the items that are in A with price bigger than (price*(exchange rate) + (some number)) in B where the item names matches. I edited the question with this follow up. So you can look at the question again for better markup and for better explanation. (I didn't know how to do markups in comments-I'm pretty new to the forum =) ). Thanks for the help! – Can Gokalp Feb 22 '17 at 19:49
  • Just so you are aware, chameleon questions are considered as inappropriate here on SO, see this [thread](http://meta.stackexchange.com/questions/43478/exit-strategies-for-chameleon-questions/130630#130630) for more detail. However, I shall try to answer your follow-up question the best way I can. You can incorporate [arithmetic operators](https://docs.mongodb.com/manual/reference/operator/aggregation-arithmetic/) in your `$redact` conditional expression, as in the edit above. – chridam Feb 22 '17 at 20:13