[SERVER-10711] $setOnInsert mods should not conflict with non-insert modifiers Created: 09/Sep/13 Updated: 06/Dec/22 Resolved: 29/Jun/19 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Write Ops |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | kic | Assignee: | Backlog - Query Team (Inactive) |
| Resolution: | Won't Do | Votes: | 46 |
| Labels: | insert, upsert | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||
| Assigned Teams: |
Query
|
||||||||||||||||||||||||||||||||
| Operating System: | ALL | ||||||||||||||||||||||||||||||||
| Participants: | |||||||||||||||||||||||||||||||||
| Description |
|
This command results in a conflict:
|
| Comments |
| Comment by Asya Kamsky [ 29/Jun/19 ] | ||||||||||||
|
You can see some examples here. This can be done by setting the array to its new value using various aggregation array expressions based on conditional expression which can determine if the fields of interest already exist or not. I believe this can handle all of the examples/use cases that were mentioned in the comments. Some of the examples given are no longer relevant in the world of WiredTiger but using a general example from one of the comments :
You can also have multiple stages, each one referencing/testing field coming from previous stage. | ||||||||||||
| Comment by Asya Kamsky [ 03/Jun/19 ] | ||||||||||||
|
joniba this issue will be resolved in an upcoming version - I'll be updating the ticket with resolution later this month. | ||||||||||||
| Comment by Jonathan Ben Ami [ 15/May/19 ] | ||||||||||||
|
Looks like this issue has been forgotten. As far as I can tell there are innumerable scenarios for this feature. If a document already exists, the consumer may want to set different data than if it does not yet exist. Any plan for this feature? | ||||||||||||
| Comment by Maga Napanga [ 28/Apr/17 ] | ||||||||||||
|
@AsyaKamsky We thought to make it less expensive for the client so it can evaluate a boolean directly instead of comparing 2 date objects. Yours is of course valid, just every need is different. | ||||||||||||
| Comment by Asya Kamsky [ 28/Apr/17 ] | ||||||||||||
|
But then won't the field just get set to false by the very next update? I'm not sure I see this use case being applicable here. You can always set updated to timestamp and created to timestamp on insert only. Then you can always tell if the document has been updated since it was created by comparing those two fields. | ||||||||||||
| Comment by Maga Napanga [ 28/Apr/17 ] | ||||||||||||
|
@Asya Kamsky That's not what I meant. I don't need to know that at the time the document is upserted, but later at any time when the document is requested by the client app. Thanks though. | ||||||||||||
| Comment by Asya Kamsky [ 27/Apr/17 ] | ||||||||||||
|
maganap the update command will return a document which tells you whether the document was upserted.
You should probably be testing that result to know if the document was updated or upserted. | ||||||||||||
| Comment by Maga Napanga [ 25/Apr/17 ] | ||||||||||||
|
Another simple use case: I need a field to be true if the document was just inserted, and to be false if it was just updated. | ||||||||||||
| Comment by Riccardo Cardin [ 06/Feb/17 ] | ||||||||||||
|
We have found this workaround http://stackoverflow.com/a/41953190/1173755 until the issue is resolved. | ||||||||||||
| Comment by Kevin Rice [ 15/Apr/16 ] | ||||||||||||
|
+1 Initialize array and put first element in it is IMPOSSIBLE with out this. | ||||||||||||
| Comment by Florian Winter [ 15/Jul/15 ] | ||||||||||||
|
+1 Much more simple use case where you run into this problem: Atomically increment and get next value of a counter, creating and initializing the counter if it doesn't exist.
where "mydb.counters" is a collection of counters, "myCounter" is the name of one such counter, "n" is the counter's value. The query above increments the counter value by 1. If it doesn't exist, the counter is initialized with 0. If this is allowed, then what should be the behavior? For the counter scenario, it would be best if only $setOnInsert (and not $inc) is applied if the counter doesn't exist. But I'm note sure if this is a good general rule. | ||||||||||||
| Comment by Michel S. [ 03/Mar/15 ] | ||||||||||||
|
+1 - Same use case as most of the people here: Create a default value before modifying it using an upsert. | ||||||||||||
| Comment by Jason Marmon [ 18/Dec/14 ] | ||||||||||||
|
+1 - we get data feeds that need to either update an existing document or create a new one; however, the updates only apply to certain portions of the document. i have to do two queries instead of one which is quite a performance hit when processing large data feeds | ||||||||||||
| Comment by John Green [ 03/Dec/14 ] | ||||||||||||
|
Slightly different case, not involving $setOnInsert - I have a data model where client can add, update, delete | ||||||||||||
| Comment by Andre Spiegel [ 15/Sep/14 ] | ||||||||||||
|
+1 for a case where you want to pre-populate an array before inserting the first value | ||||||||||||
| Comment by David Stevens [ 09/Sep/14 ] | ||||||||||||
|
+1 for use case creating multiple default values | ||||||||||||
| Comment by Mike Lohmeier [ 20/Aug/14 ] | ||||||||||||
|
+1 running into this issue when trying to store sensor data in a time series collection. | ||||||||||||
| Comment by Thomas Rueckstiess [ 15/Aug/14 ] | ||||||||||||
|
This issue is still present in 2.6:
It prevents a very common use case: Initialize counters when the document does not yet exist, or else increase counters. | ||||||||||||
| Comment by Tim S [ 14/Aug/14 ] | ||||||||||||
|
+1 to fix this, simply ignore the $inc or have $setOnInsert override, can't be tough to do. | ||||||||||||
| Comment by Patrick Shelby [ 09/Apr/14 ] | ||||||||||||
|
This is creating conflicts for my inserts as well. A workaround would be expensive in both the database and the inserting script. | ||||||||||||
| Comment by William Cross [ 01/Apr/14 ] | ||||||||||||
|
I ran into this issue as well, with jacob.ribnik while making questions for an exam. I know he's run into it, separately. | ||||||||||||
| Comment by Matthew Back [ 04/Dec/13 ] | ||||||||||||
|
This issue has become a problem for me. >db.mycollection.update({_id:{timestamp: new ISODate('2013-11-25T07:40:00Z'), action:'BK', protocol:'http'}}, , ) | ||||||||||||
| Comment by Jon Rangel (Inactive) [ 20/Nov/13 ] | ||||||||||||
|
One use case for this is in pre-allocating documents for pre-aggregated reports, to avoid growing documents. The pre-allocation strategy advocated in the documentation is to allocate documents in batch up-front or probabilistically over some appropriate time interval. The drawback with this approach is that documents may be created that are not subsequently used, and are thus a waste of space. For example, consider the following daily stats document with hourly buckets:
In this example, a given event might not occur every day so it is undesirable to create documents for days when the event does not occur. |