[SERVER-20203] upsert querying an array field and $push-ing to that same field yields confusing error Created: 30/Aug/15 Updated: 07/Apr/23 Resolved: 16/Sep/15 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Write Ops |
| Affects Version/s: | 2.6.0 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Evan Altman | Assignee: | Max Hirschhorn |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||
| Operating System: | ALL | ||||||||||||
| Sprint: | Quint 9 09/18/15 | ||||||||||||
| Participants: | |||||||||||||
| Description |
|
When attempting to query on one field of an array element, the docs make it very clear that $elemMatch is not necessary. For example, find({"list.field":"value"}) should match the following document: { "list":[ {"field":"value"}, {"otherField":"otherValue"} ] }. However, doing an upsert using findAndModify on an empty collection:
causes the following error: |
| Comments |
| Comment by Max Hirschhorn [ 15/Sep/15 ] | |||||||
|
Hi Evan, Thanks for reporting this. As you've pointed out, the behavior of {"list.field": value} as a query predicate is different from {list: {$elemMatch: {field: value}}} during an update or findAndModify operation when the document isn't found and upsert=true.
This is behavior is described in our documentation for upsert:
Internally, a base document is constructed and then the specified update modifiers are applied to it. All equality matches of the form {field: value} are assumed to refer to a document, even though nested fields could also refer to an array of subdocuments. Since $elemMatch is not an equality match, no equality match is extracted from the query predicate. With regard to the previous examples, the base document {list: {field: "value"}} is constructed from the query {"list.field": "value"} and the base document {} is constructed from the query {list: {$elemMatch: {field: "value"}}}. The $push modifier cannot be applied to the list field because it contains a subdocument and is not an array, hence the error message. However, the $push modifier can be applied to an empty document, which adds the field to the document as a singleton array element. Hope that helps, | |||||||
| Comment by Sam Kleinman (Inactive) [ 03/Sep/15 ] | |||||||
|
Thanks for this report and sorry for the confusion. We'll get this evaluated and triaged as soon as possible. | |||||||
| Comment by Evan Altman [ 30/Aug/15 ] | |||||||
|
I should note that using $elemMatch for the query (instead of {list.field":"value"}) does work fine. |