Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

MongoDB - Update or Insert object in array

I have the following collection

{
    "_id" : ObjectId("57315ba4846dd82425ca2408"),
    "myarray" : [ 
        {
            userId : ObjectId("570ca5e48dbe673802c2d035"),
            point : 5
        },
        {
            userId : ObjectId("613ca5e48dbe673802c2d521"),
            point : 2
        },        
     ]
}

These are my questions

I want to push into myarray if userId doesn't exist, it should be appended to myarray. If userId exists, it should be updated to point.

I found this

db.collection.update({
    _id : ObjectId("57315ba4846dd82425ca2408"),
    "myarray.userId" :  ObjectId("570ca5e48dbe673802c2d035")
}, {
    $set: { "myarray.$.point": 10 }
})

But if userId doesn't exist, nothing happens.

and

db.collection.update({
    _id : ObjectId("57315ba4846dd82425ca2408")
}, {
  $push: {
      "myarray": {
          userId: ObjectId("570ca5e48dbe673802c2d035"),
          point: 10
      }
  }
})

But if userId object already exists, it will push again.

What is the best way to do this in MongoDB?

question from:https://stackoverflow.com/questions/37427610/mongodb-update-or-insert-object-in-array

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The accepted answer by Flying Fisher is that the existing record will first be deleted, and then it will be pushed again.

A safer approach (common sense) would be to try to update the record first, and if that did not find a match, insert it, like so:

// first try to overwrite existing value
var result = db.collection.update(
   {
       _id : ObjectId("57315ba4846dd82425ca2408"),
       "myarray.userId": ObjectId("570ca5e48dbe673802c2d035")
   },
   {
       $set: {"myarray.$.point": {point: 10}}
   }
);
// you probably need to modify the following if-statement to some async callback
// checking depending on your server-side code and mongodb-driver
if(!result.nMatched)
{
    // record not found, so create a new entry
    // this can be done using $addToSet:
    db.collection.update(
        {
            _id: ObjectId("57315ba4846dd82425ca2408")
        },
        {
            $addToSet: {
                myarray: {
                    userId: ObjectId("570ca5e48dbe673802c2d035"),
                    point: 10
                }
            }
        }
    );
    // OR (the equivalent) using $push:
    db.collection.update(
        {
            _id: ObjectId("57315ba4846dd82425ca2408"),
            "myarray.userId": {$ne: ObjectId("570ca5e48dbe673802c2d035"}}
        },
        {
            $push: {
                myarray: {
                    userId: ObjectId("570ca5e48dbe673802c2d035"),
                    point: 10
                }
            }
        }
    );
}

This should also give (common sense, untested) an increase in performance, if in most cases the record already exists, only the first query will be executed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...