简体   繁体   中英

How can I use variables in an update operation in mongodb that involves an array or another type of embedded or nested document?

The document in the target collection ("myCollection") has a field called "japanese2". This is an array (or an object) that contains an object that contains a property called "japanese2a". The value of this property is initially set to 0 (although it may change later). I want to change this value to 100 with a script in node.js (I am using the Express framework). The database is Mongodb, the free cloud version called Atlas.

If I do this without using variables, it works well:

db
 .collection("myCollection")
 .updateOne({username:username}, {"$set":{"japanese2.0.japanese2a":100}});

However, if I try this using variables for both the field name, "japanese2", and the name of the element/property in the array/object, "japanese2a", it fails. I have tried the below and other variations but I couldn't find a solution. I have researched stackoverflow for an answer but couldn't find a solution.

There is only one element/property in the array/object to start with.

     var field = req.body.fieldName; //want to set this for the field name="japanese2"
     var task = req.body.question; //want to set this for the name of the element="japanese2a"
     var myField = [task];
     field = myField; 
     var fieldPos = field[0];
.
.
.
db
 .collection("myCollection")
 .updateOne({username:username}, {"$set":{[fieldPos]:100}});

The above creates a new field called "japanese2a":100" but it does not appear in the array under the field called "japanese2", which is what I want.

I don't get any error messages when I do the above in the console (probably mostly due to the fact that I haven't put in error statements/functions to catch errors), but the output is not correct.

Another way of updating that I found from here: https://www.codementor.io/@prasadsaya/working-with-arrays-in-mongodb-16s303gkd3

that involves using something like this:

db.posts.updateOne( 
  { _id : ObjectId("5ec55af811ac5e2e2aafb2b9"), "comments.user": "Database Rebel" },
  { $set: { "comments.$.text": NEW_CONTENT } }
)

doesn't work for me, as I don't know if the initial value of the element in the array will always be a zero or some other constant. And there is only one element in the array initially. I can only use the username for the match part in the updating. I can't make an expression that is a perfect match for some element in the array.

The update solution from here: MongoDB update data in nested field

db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });

works, and that is what I used successfully to update in the first updating attempt above, but I don't know how to incorporate variables into the updating operation, specifically a variable for the field name ("japanese2") that holds the array or the object, and the name of the first and only element/property in the array/object ("japanese2a").

EDITED: I asked for a solution for an "array" originally, but either a field that acts an array (that holds elements that act as objects) or an object (that holds other objects as properties) works in my case, so I edited the question body and title. Also, the accepted solution works with the field as an entity that holds an array, or as an entity that contains an object inside it.

In either case, if there is already a field with the appropriate name, an object is created (if it didn't already exist) as an object of that object called "field" or the array called "field", and the object's property is set as according to the variables in the script.

If the field doesn't exist, it's created (as an object), and this object contains another object that contains the property ("task" as the name and "100" as the value for the name-value pair). So the newly created "field" object contains an object as its property. The property of this object is a name-value pair of "japanese2a" and "100".

If the script is run again, with a different "task" name (eg. "japanese2b"), another property is created, with the name of "japanese2b" and the value of "100". It is created within that same object that is "inside" the "field" object, so the object field.0 (the object within the "field" object) ends up looking like this: {japanese2a: 100, japanese2b: 100} . And the object called "field" looks like this: {{japanese2a: 100, japanese2b: 100}} .

I think something like

var field = req.body.fieldName // japanese2
var task = req.body.question; // japanese2a
var updateObj = { $set : {} };

updateObj.$set[field + '.0.' + task] = 100

db
  .collection("myCollection")
  .updateOne({username:username}, updateObj);

Might work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM