[SERVER-4753] array indexes and object subfields should be referenced with different syntax Created: 24/Jan/12  Updated: 06/Dec/22

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

Type: New Feature Priority: Major - P3
Reporter: Neil Sanchala Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 4
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Related
is related to SERVER-28779 Allow $[] syntax for specifying array... Backlog
is related to SERVER-13478 Resolve ambiguity of positional array... Backlog
Assigned Teams:
Query Optimization
Participants:

 Description   

It is currently the case that if you send an update like:

{ $set:

{ "foo.0": "x" }

}

You may be updating either index 0 of the array foo or the key "0" in an object. If "foo" exists as an array, then it updates index 0. If it's an object, it updates the key "0". The problem is that if "foo" doesn't yet exist, then mongo assumes you want an object.

This has bitten us a couple times, where we've ended up with objects with numeric keys, instead of arrays.

Ideally the syntax for these two cases would be different so there wouldn't be ambiguity. For example, array indexes could be referenced with []. It would be difficult to ever deprecate the old dot notation, but callers could switch to the square brackets and not run the risk of having this problem.



 Comments   
Comment by Andrei Stepanov [ 09/Jul/21 ]

Hi, is there any solution for this ticket? Working example would be good. Thank you.

Comment by Neil Sanchala [ 04/Apr/12 ]

$idx is fine by me.

Comment by Glenn Maynard [ 04/Apr/12 ]

It's a bit ugly, but

{"foo.$[0]": "X"}

is unambiguous, since an object key can't begin with $.

"foo.$idx[0]" might be a bit more future-proof.

I strongly recommend against "foo[0]". I have to parse and navigate dotted paths by hand now and then, and that's a lot more work to parse compared to 'a.b.c'.split('.'). It's also still ambiguous. (Please don't make brackets special in field names! There are already too many keys which are valid JSON object keys that aren't allowed as keys in Mongo, like email addresses.)

Comment by Neil Sanchala [ 25/Jan/12 ]

Got it, thanks for the explanation.

Comment by Scott Hernandez (Inactive) [ 25/Jan/12 ]

I think Eliot was just suggesting it as it would break less things since we already have the dot - ordinal notation for arrays, and somewhat special handling for that whole field name (in dot notation) for the ".#."

Comment by Neil Sanchala [ 25/Jan/12 ]

But if you only use dots for objects and square brackets for arrays there's no potential ambiguity, and no concerns about existing data with "[0]" as a key name in an embedded object. Is there an advantage to using dot-then-square-brackets in the array case given that it introduces ambiguity?

Comment by Scott Hernandez (Inactive) [ 25/Jan/12 ]

It is not currently a valid way, no. But the idea is that it could be a syntax to allow more explicit behavior when inserting/update+upsert to affirm you want an array and not a field name.

As you said, unless there are characters which cannot be used in field names then this could be ambiguous and confusing to some (even if some is < .001 %). It is also possible to declare brackets numbers as special in field names... so that at least it is documented.

Comment by Neil Sanchala [ 25/Jan/12 ]

is foo.[0] a valid way to reference the key "[0]" in the object foo? if so, i'm not a big fan since there's still some ambiguity there – mongo would have to decide whether an update to foo.[0] is supposed to change an object subfield or an array index, and if the foo key doesn't exist, has to decide whether to make an object or an array. making that decision based on the format of the key is unintuitive at the least, and will bite someone else in the long run.

Comment by Eliot Horowitz (Inactive) [ 25/Jan/12 ]

this could work:

{ $set : { "foo[0]" : "X" } }

this might be less breaking:

{ $set : { "foo.[0]" : "X" } }

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