3

Considering this query written in sql server how would I efficiently convert it to mongodb:

select * from thetable where column1 = column2 * 2

4 Answers 4

4

You can use below aggregation.

You project a new field comp to calculate the expression value followed by $match to keep the docs with eq(0) value and $project with exclusion to drop comp field.

db.collection.aggregate([
   { $addFields: {"comp": {$cmp: ["$column1",  {$multiply: [ 2, "$column2" ]} ]}}},
   { $match: {"comp":0}},
   { $project:{"comp":0}}
])
Sign up to request clarification or add additional context in comments.

Comments

1

If you want to run your query in mongo Shell, try below code,

db.thetable .find({}).forEach(function(tt){
    var ttcol2 = tt.column2 * 2
    var comapreCurrent =  db.thetable.findOne({_id : tt._id,column1 : ttcol2});
    if(comapreCurrent){
       printjson(comapreCurrent);
    }
});

Comments

0

I liked the answer posted by @Veeram but it would also be possible to achieve this using $project and $match pipeline operation. This is just for understanding the flow

Assume we have the below 2 documents stored in a math collection

Mongo Documents

    {
        "_id" : ObjectId("58a055b52f67a312c3993553"),
        "num1" : 2,
        "num2" : 4
    }

    {
        "_id" : ObjectId("58a055be2f67a312c3993555"),
        "num1" : 2,
        "num2" : 6
    }

Now we need to find if num1 = 2 times of num2 (In our case the document with _id ObjectId("58a055b52f67a312c3993553") will be matching this condition)

Query:

    db.math.aggregate([
      {
        "$project": {
          "num2": {
            "$multiply": ["$num2",1]
          },
          "total": {
            "$multiply": ["$num1",2]
          },
          "doc": "$$ROOT"
        }
      },
      {
        "$project": {
          "areEqual": {"$eq": ["$num2","$total"]
          },
          doc: 1
        }
      },
      {
        "$match": {
          "areEqual": true
        }
      },
      {
        "$project": {
          "_id": 1,
          "num1": "$doc.num1",
          "num2": "$doc.num2"
        }
      }
    ])

Pipeline operation steps:-

  • The 1st pipeline operation $project calculates the total
  • The 2nd pipeline operation $project is used to check if the total matches the num2. This is needed as we cannot use the comparision operation of num2 with total in the $match pipeline operation
  • The 3rd pipeline operation matches if areEqual is true
  • The 4th pipeline operation $project is just used for projecting the fields

Note:- In the 1st pipeline operation I have multiplied num2 with 1 as num1 and num2 are stored as integers and $multiply returns double value. So incase I do not use $mutiply for num2, then it tries to match 4 equals 4.0 which will not match the document.

Comments

0

Certainly no need for multiple pipeline stages when a single $redact pipeline will suffice as it beautifully incorporates the functionality of $project and $match pipeline steps. Consider running the following pipeline for an efficient query:

db.collection.aggregate([
    { 
        "$redact": { 
            "$cond": [
                { 
                    "$eq": [ 
                        "$column1", 
                        { "$multiply": ["$column2", 2] }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

In the above, $redact will return all documents that match the condition using $$KEEP and discards those that don't match using the $$PRUNE system variable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.