[SERVER-35969] $setOnInsert executes javascript dispite lack of insertion Created: 05/Jul/18  Updated: 27/Oct/23  Resolved: 06/Jul/18

Status: Closed
Project: Core Server
Component/s: JavaScript, Usability, Write Ops
Affects Version/s: 3.4.10, 3.4.15
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Jack Luo Assignee: Backlog - Query Team (Inactive)
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Query
Operating System: ALL
Steps To Reproduce:

 

db.system.js.save({
 _id: "nextId", 
 value: function (x) {
    return db.counters.findAndModify({
      query:{_id:x}, 
      update:{$inc:{value:1}}, 
      new:true
    }).value;
 }
})
db.loadServerScripts()  // make the nextId available directly
db.counters.insert({_id: "_id", value: 0})
db.counters.find({})     // shows that counter is 0
db.test.update(
    {"value": "abc"},
    {$setOnInsert: {"_id": nextId("_id"), "value": "abc"}},
    {upsert: true}
)
db.counters.find({}) // previous update upserted and shows that counter is incremented to 1
db.test.update(
    {"value": "abc"},
    {$setOnInsert: {"_id": nextId("_id"), "value": "abc"}},
    {upsert: true}
)
db.counters.find({}) // previous update does not modify document, however counter is incremented to 2

 

Participants:

 Description   

https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/

According to the documentation, "If the update operation does not result in an insert,$setOnInsert does nothing." 

This statement is not true for all cases. The documentation should be changed to "$setOnInsert does insert values" or equivalent rather than "$setOnIN=nsert does nothing". In the case where javascript function is specified inside $setOnInsert clause, the javascript function is still executed dispite no document insertion.

Reproduction steps is verified on mongodb 3.4.10 and 3.4.15.



 Comments   
Comment by David Storch [ 06/Jul/18 ]

Hi jackluo923,

Thanks for filing this bug report. The server query team has reviewed this case and believe that the system is working as designed.

The effect of db.loadServerScripts() is to load the contents of the system.js collection into the shell. Therefore, your invocation of the function nextId() is running on the client side. (In fact, the update language does not currently support server-side JavaScript execution.) It is indeed the case that system.js is used to make functions available for server-side JS execution. You'll notice, however, that if you do not load system.js into the shell, your repro steps will not run successfully due to the nextId function being unknown.

Please feel free to comment on this ticket with any questions or concerns.

Best,
Dave

Generated at Thu Feb 08 04:41:37 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.