Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb - aggregation $push if conditional

I am trying to aggregate a batch of documents. There are two fields in the documents I would like to $push. However, lets say they are "_id" and "A" fields, I only want $push "_id" and "A" if "A" is $gt 0.

I tried two approaches.

First one.

db.collection.aggregate([{ "$group":{     "field": {         "$push": {             "$cond":[                 {"$gt":["$A", 0]},                 {"id": "$_id", "A":"$A"},                 null             ]         }     },     "secondField":{"$push":"$B"} }]) 

But this will push a null value to "field" and I don't want it.

Second one.

db.collection.aggregate([{ "$group":     "field": {         "$cond":[             {"$gt",["$A", 0]},             {"$push": {"id":"$_id", "A":"$A"}},             null         ]     },     "secondField":{"$push":"$B"} }]) 

The second one simply doesn't work...

Is there a way to skip the $push in else case?

ADDED:

Expected documents:

{     "_id":objectid(1),     "A":2,     "B":"One" }, {     "_id":objectid(2),     "A":3,     "B":"Two" }, {     "_id":objectid(3),     "B":"Three" } 

Expected Output:

{     "field":[         {             "A":"2",             "_id":objectid(1)         },         {             "A":"3",             "_id":objectid(2)         },     ],     "secondField":["One", "Two", "Three"] } 
like image 345
Artorias Avatar asked Apr 06 '18 06:04

Artorias


People also ask

How do I use $Push in MongoDB?

In MongoDB, the $push operator is used to appends a specified value to an array. If the mentioned field is absent in the document to update, the $push operator add it as a new field and includes mentioned value as its element. If the updating field is not an array type field the operation failed.

Is aggregation fast in MongoDB?

On large collections of millions of documents, MongoDB's aggregation was shown to be much worse than Elasticsearch. Performance worsens with collection size when MongoDB starts using the disk due to limited system RAM. The $lookup stage used without indexes can be very slow.

Is aggregation faster than find?

Without seeing your data and your query it is difficult to answer why aggregate+sort is faster than find+sort. A well indexed(Indexing that suits your query) data will always yield faster results on your find query.


2 Answers

You can use "$$REMOVE":

  • This system variable was added in version 3.6 (mongodb docs)
db.collection.aggregate([{    $group:{        field: {           $push: {               $cond:[                 { $gt: ["$A", 0] },                 { id: "$_id", A:"$A" },                 "$$REMOVE"             ]           }         },         secondField:{ $push: "$B" }     } ]) 

In this way you don't have to filter nulls.

like image 84
Elad Amsalem Avatar answered Oct 09 '22 21:10

Elad Amsalem


This is my answer to the question after reading the post suggested by @Veeram

db.collection.aggregate([{ "$group":{     "field": {         "$push": {             "$cond":[                 {"$gt":["$A", 0]},                 {"id": "$_id", "A":"$A"},                 null             ]         }     },     "secondField":{"$push":"$B"} }, {     "$project": {         "A":{"$setDifference":["$A", [null]]},         "B":"$B"     } }]) 
like image 42
Artorias Avatar answered Oct 09 '22 20:10

Artorias