[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: |
|
||||||||||||||||
| 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:
this might be less breaking:
|