[SERVER-20014] Question about aggregation behavior Created: 18/Aug/15  Updated: 21/Sep/15  Resolved: 21/Sep/15

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: 3.0.5
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Ben Rotz Assignee: Asya Kamsky
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Participants:

 Description   

The following behavior seems like a bug to me:

> db.test.insert({ "_id" : ObjectId("55d386eeb4a9494cd24e94fc"), "name" : "test", "myarray" : [ ] });
WriteResult({ "nInserted" : 1 })
> db.test.aggregate([{'$group' : {'_id' : '$name', 'thing' : {'$first' : '$myarray.made_up_field'}}}]);
{ "_id" : "test", "thing" : [ ] }

Why does "thing" get set to an empty array? It should be null?

I ran into this problem while doing a $push like the following during a $group phase

'inventory' => ['$push' => [
  warehouse' => '$sku.inventory.warehouse',
  at_once' => '$sku.inventory.at_once'
]]

and getting an empty array for warehouse often times instead of a string when sku.inventory was an empty array.



 Comments   
Comment by Ramon Fernandez Marina [ 21/Sep/15 ]

This is (currently) the expected behavior, so I'm closing this ticket as "Works as Designed".

Regards,
Ramón.

Comment by Ben Rotz [ 19/Aug/15 ]

Since $myarray.made_up_field is null (does not exist), I would expect "thing" to be null as well. The problem I was experiencing was really due to the fact that the $unwind operator returns no rows for an empty array field (as explained here: http://stackoverflow.com/questions/22114748/unwind-empty-array-in-mongodb) , and the only way around that behavior is to project like so:

'project' : {
    '_id' : '$_id',
    'sku' : [
        'inventory' : { '$cond' : { 'if' : [ '$eq' : [ '$sku.inventory', [] ] ], 'then' : [{}], 'else' : '$sku.inventory' } }
    ]
}

Thereby making sku.inventory have an "empty value" so when I unwound it, it didn't disappear. But, I was a dummy and was using [ [ ] ] instead of [ { } ] as my value, as I should have done. So I was able to make it work. It just threw me for a loop that when doing $first or $push on an an undefined field (even if it is a child of an array field that does not exist), it should be null, right?

Overall, weird use case and not a big deal.

As mentioned, if you set myarray/myobj to an empty object instead of an empty array, $first/etc. results in null as expected.

> db.test.insert({ "name" : "test", "myobj" : {} });
WriteResult({ "nInserted" : 1 })
> db.test.aggregate([{'$group' : {'_id' : '$name', 'thing' : {'$first' : '$myobj.made_up_field'}}}]);
{ "_id" : "test", "thing" : null }

Comment by Asya Kamsky [ 18/Aug/15 ]

nefiga it seems to me like this is doing the correct thing - can you explain why you don't expect an array when you're pushing an array (or giving $array to $first)?

Generated at Thu Feb 08 03:52:52 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.