[SERVER-59713] `$unwind` doesn't work on array subdocument fields Created: 01/Sep/21 Updated: 17/Jan/24 |
|
| Status: | Investigating |
| Project: | Core Server |
| Component/s: | None |
| Affects Version/s: | 4.4.2 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Amit Beckenstein | Assignee: | Katya Kamenieva |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | $unwind, aggregation-framework | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||
| Operating System: | ALL | ||||||||||||||||
| Steps To Reproduce: |
items: [ { _id: ObjectId, name: 'foobar' {{ }}} ] });
Outputs nothing |
||||||||||||||||
| Participants: | |||||||||||||||||
| Description |
|
Given the following document: db.collection.insertOne({ items: [ { _id: ObjectId, name: 'foobar' {{ }}} ] }); Trying to `$unwind` the field path `$items.name` outputs nothing. On the other hand, the output of this: db.collection.aggregate([ is the following: {{{}} If the expression `$items.name` resolves to an array then why can I not `$unwind` this field path? |
| Comments |
| Comment by Johnny Shields [ 17/Jan/24 ] | ||||||||||||||||||||||||||
|
kateryna.kamenieva@mongodb.com christopher.harris@mongodb.com may we get an update on this ticket? It's been in "Investigating" status for quite sometime. Please refer to | ||||||||||||||||||||||||||
| Comment by William Tan (Inactive) [ 12/Apr/23 ] | ||||||||||||||||||||||||||
|
Changing the type of this ticket to "Bug" upon customer request. | ||||||||||||||||||||||||||
| Comment by Amit Beckenstein [ 10/Feb/23 ] | ||||||||||||||||||||||||||
|
@Johnny Shields haha I know that I can use `$project`, in my actual implementation I was using `$addFields` intentionally. | ||||||||||||||||||||||||||
| Comment by Johnny Shields [ 10/Feb/23 ] | ||||||||||||||||||||||||||
|
@christopher.harris@mongodb.com > | ||||||||||||||||||||||||||
| Comment by Johnny Shields [ 10/Feb/23 ] | ||||||||||||||||||||||||||
|
FYI, you can use a $project instead of $addFields in order to avoid modifying your documents.
But this still should be fixed. | ||||||||||||||||||||||||||
| Comment by Amit Beckenstein [ 07/Sep/22 ] | ||||||||||||||||||||||||||
|
@christopher.harris@mongodb.com Any update? It's been almost a year | ||||||||||||||||||||||||||
| Comment by Amit Beckenstein [ 22/Sep/21 ] | ||||||||||||||||||||||||||
|
Hi @christopher.harris, The system might very well be working as designed currently. I'm not sure if this is a bug or a feature request, but I'll do my best to explain my use case for support of such functionality. First, to answer your request: the output I would expect when issuing an $unwind on "$arrayField.stringValue" (which is the equivalent to "$items.name" in my example, yes) is the same output which I would expect when issuing an $unwind on "$arrayField" itself. An excerpt of my use case is such:
As seen above, I have to $unwind an array whose field path is specified in parameterFieldPath (which is "$items.name" in our example), and then $group the output documents by the same parameterFieldPath. parameterFieldPath is variable, and its value can be changed according to a user's settings.
But this leaves me with an unwanted temporary parameterValue field on each document. BTW the TODO is taken from our code I hope my use case was clear enough. Thanks,
| ||||||||||||||||||||||||||
| Comment by Chris Harris [ 20/Sep/21 ] | ||||||||||||||||||||||||||
|
Based on our reading of the ticket description, we believe that the system may be working as designed currently. However, can you please give an example of what output you would expect when issuing an $unwind on "$arrayField.stringValue" ( "$items.name" in your example)? Based on the workaround you noted, it seems you are looking to create documents that each contain the value of the name field that is embedded in one of the subdocuments in the items array? The $unwind operator intends to have a field name that resolves to an array as its argument. This is why, as you've observed, the stage { $unwind: "$temp" } outputs results. In that situation, $temp now represents an array of string values that was generated from the original array of subdocuments. You could similarly choose to $unwind the array of subdocuments ( $items ) first and then rename or remove fields afterwards based on the desired logic. Furthermore, it is also possible to use or reference the individual values via the "$items.name" syntax in later aggregation stages after the "items" array has been unwound. How are you intending to use this field later in the aggregation pipeline? Similar confusion has come up before. The fact that the projection using the $type operator reported the field path as an array has to do with the fact that the $type aggregation operator does not examine array elements. Depending on the feedback you provide to the questions above, we may wish to convert this ticket into an improvement request. Best, | ||||||||||||||||||||||||||
| Comment by Kelsey Schubert [ 13/Sep/21 ] | ||||||||||||||||||||||||||
|
Thanks for the report, passing this along to the query team to investigate. Please continue to watch this ticket for updates. | ||||||||||||||||||||||||||
| Comment by Amit Beckenstein [ 01/Sep/21 ] | ||||||||||||||||||||||||||
|
The workaround for now is something of the sorts:
db.collection.aggregate([ { $addFields: temp: '$items.name' }, { $unwind: '$temp' } ]); |