[SERVER-29846] new field name changes expression result for array in $project Created: 24/Jun/17 Updated: 27/Oct/23 Resolved: 27/Jun/17 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Aggregation Framework |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Asya Kamsky | Assignee: | Asya Kamsky |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Backwards Compatibility: | Fully Compatible |
| Operating System: | ALL |
| Participants: |
| Description |
|
Or another way of stating the issue is, I cannot change array field to non-array field if I want to use any of its contents in the expression (without changing its name).
I can change it to be embedded inside another field like this:
However, if I need the top level name of new field is to be "a" then there seems to be no way to avoid projection happening for every element of original array:
I haven't found a way to do this except by having two $projects, one to create newA and the second to rename newA to a. I understanding adding fields to existing arrays of objects requires preserving cardinality (and type) of array field, but this seems to be a full replace. Looked for existing ticket related to this, |
| Comments |
| Comment by Asya Kamsky [ 27/Jun/17 ] | ||||||||||||||
|
The challenge appears to be the fact that "a.b" for an existing field has to take into account the existing structure of "a" - if "a" is an array then field "b" needs to be set in every element of array "a". If "a" is scalar then "b" replaces the scalar field. The scenario I wanted in this case is possible to achieve by using a new field name (and then renaming via an extra $project or $addFields stage if necessary) but using $replaceRoot may be more readable, and it would have the advantage of being a single stage. For completeness here is how to achieve the result I expected in the original $project via $replaceRoot:
To get the effect of $addFields stage to set the new "a" in place of existing field "a" while retaining the existing fields, $mergeObjects (new in 3.5) is needed:
| ||||||||||||||
| Comment by Charlie Swanson [ 26/Jun/17 ] | ||||||||||||||
|
asya we parse these two to the same thing to ensure that "a.b" and a: {b: ...} always mean the same thing:
Are you trying to say that the first one seems more like a replacement, and the second more like a traversal? I can see that point, but this would definitely be a backwards breaking change. I of course wasn't around for the initial design of $project, but I was under the impression that we invented this syntax so that something like
could be condensed into something like this:
Have you tried a $replaceRoot? |