1

If I have collection with some documents, which have the form:

{
    "_id" : ObjectId("53202e1d78166396592cf805"),
    "a" : 4,
    "b" : 2,
    "c" : 4,
    "d" : 3
}

How to select documents with this condition:

db.stat.find({'a' + 'b' > 'c' + 'd'})

Possible, use aggregation, but then what condition in section "macth":

db.stat.aggregate([
 {$project : {
      _id : '$_id',   
      'ab' : { '$add' : [ '$a', '$b' ] },
      'cd' : { '$add' : [ '$c', '$d' ] }
     }},
     {$match: {???}}
]);

Interested the solution without mapReduce and without artificial methods of comparing the value to zero ($subtract:["$ab", "$cd"] > 0).

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Gh0stik
  • 145
  • 6
  • In your match why don't you just use http://docs.mongodb.org/manual/reference/operator/aggregation/cmp/ to see what way it is? But then that is pretty much the sme as substraction – Sammaye Mar 13 '14 at 11:35
  • @NeilLunn yeah your answer is the right one here, dunno why I wrote what I did – Sammaye Mar 13 '14 at 12:09

1 Answers1

3

Well there would be one more step before a $match:

db.stat.aggregate([
    { "$project" : {
        "ab": { "$add" : [ "$a", "$b" ] },
        "cd":  { '$add' : [ "$c", "$d" ] }
    }},
    { "$project": {
        "matched": {"$gt": [ "$ab", "$cd" ] }
    }},
    { "$match": { "matched": true } }
])

Or even better:

db.stat.aggregate([
    { "$project": {
        "matched": { "$gt": [
            { "$add" : [ "$a", "$b" ] },
            { "$add" : [ "$c", "$d" ] } 
        ]}
    }},
    { "$match": { "matched": true } }
])

For an overview of keeping your original document see here.

Of course there is always this, well "not pretty" form:

db.stats.find(function() {
     return ( ( this.a + this.b ) > (this.c + this.d) );
})

But that is a shortcut to the $where operator form, which will remove your ability to use an index for selection.

So hopefully you can to an initial $match to select the documents you want to test like this, and therefore the aggregation way is better as that initial $match can use an index.

Community
  • 1
  • 1
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317