[SERVER-55195] Should {a:[[]]} match {a: {$size:0}} Created: 15/Mar/21  Updated: 06/Dec/22

Status: Backlog
Project: Core Server
Component/s: Querying
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Mathias Stearn Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Query Optimization
Sprint: Query Optimization 2021-05-03
Participants:

 Description   

Currently it doesn't, but it seems like it should, since our general semantics would check if any elem in an array matches the predicate. It is seems especially odd since we already do traverse arrays in the path in some cases for size.

> db.arr_stress.insert({a:[[]]})
WriteResult({ "nInserted" : 1 })
> db.arr_stress.insert({a:[{b:[]}]})
WriteResult({ "nInserted" : 1 })
 
> db.arr_stress.find({a:{$size:0}})
> db.arr_stress.find({'a.b':{$size:0}})
{ "_id" : ObjectId("604f86bbe25682f5583b49d0"), "a" : [ { "b" : [ ] } ] }
 
> db.arr_stress.find({a:[]})
{ "_id" : ObjectId("604f8628e25682f5583b49cf"), "a" : [ [ ] ] }
> db.arr_stress.find({'a.b':[]})
{ "_id" : ObjectId("604f86bbe25682f5583b49d0"), "a" : [ { "b" : [ ] } ] }

Making {a: {$size: 0}} match here would mean that it is now equivalent to {a:[]}. I'm not sure if that is an argument for or against changing it, but it seemed worth noting.



 Comments   
Comment by Mathias Stearn [ 06/May/21 ]

As I said, I'm not sure it is a bug, just a somewhat surprizing quirk in our language. I wasn't expecting it to be fixed immediately, since that would be a breaking semantic change, instead I filed it to record something else to add to the list of things to think about when designing MQL 2.0 (or 1.N+1 if we just add things).

Maybe I'm wrong, but I feel like $size is the only operator that only does partial implicit array traversal (note that it does do some traversal in the {'a.b': {$size: 0}} case, so I would disagree that it doesn't do traversal). At least in my mental model, $elemMatch does do traversal, and applies the inner predicate on the traversed nodes.

Another way to look at this is that we need an "anti-$elemMatch" (strawman name: $fieldMatch). Then we could say that {$size:0}'s current behavior is the same as {$fieldMatch: []}. It would then be an open question whether we would want $size to continue to have the implicit $fieldMatch behavior (I could certainly see justification for it), or if we want to allow users to use it to match arrays-of-arrays (which admittedly aren't well supported by the rest of our query language,)

Generated at Thu Feb 08 05:35:45 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.