Search code examples
javascriptmongodbargumentsupdatemodel

How could I run this as one command in Mongo Shell


db.people.update(
    { "age": "Thirty Two" }, { age: 32 }, { upsert: false }
)

db.people.update(
    { "age": "Fifty-Five" }, { age: 55 }, { upsert: false }
)

db.people.update(
    { "age": "Twenty" }, { age: 20 }, { upsert: false }
)

I was thinking:

db.people.update(
    [{ "age": "Thirty Two" }, { age: 32 }, { upsert: false }],
    [{ "age": "Fifty-Five" }, { age: 55 }, { upsert: false }],
    [{ "age": "Twenty" }, { age: 20 }, { upsert: false }]
)

But that didn't work.. I know im just really tired and can't think of it...


Solution

  • To elaborate on my comment and present an alternative to db.eval(), a "operatorless" update replaces the entire matched document with the update document (except keeping the _id):

    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 32 }
    { "_id" : 1, "name" : "Sam Small", "age" : 26 }
    { "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
    > db.people.update({ "age" : 32 }, { "age" : 45 })
    > db.people.find()
    { "_id" : 0, "age" : 45 }
    { "_id" : 1, "name" : "Sam Small", "age" : 26 }
    { "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
    

    Changing only one field means using an update operator like $set:

    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 32 }
    { "_id" : 1, "name" : "Sam Small", "age" : 26 }
    { "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
    > db.people.update({ "age" : 32 }, { "$set" : { "age" : 45 } })
    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 45 }
    { "_id" : 1, "name" : "Sam Small", "age" : 26 }
    { "_id" : 2, "name" : "Mindy Medium", "age" : 26 }
    

    By default, updates affect only one matching document. The option multi=true will cause the update to affect all matching documents:

    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 32 }
    { "_id" : 1, "name" : "Larry Large", "age" : 32 }
    { "_id" : 2, "name" : "Sam Small", "age" : 26 }
    { "_id" : 3, "name" : "Mindy Medium", "age" : 26 }
    > db.people.update({ "age" : 32 }, { "$set" : { "age" : 45 } })
    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 45 }
    { "_id" : 1, "name" : "Larry Large", "age" : 32 }
    { "_id" : 2, "name" : "Sam Small", "age" : 26 }
    { "_id" : 3, "name" : "Mindy Medium", "age" : 26 }
    > db.people.update({ "age" : 26 }, { "$set" : { "age" : 23 } }, { "multi" : true })
    > db.people.find()
    { "_id" : 0, "name" : "Barney Big", "age" : 45 }
    { "_id" : 1, "name" : "Larry Large", "age" : 32 }
    { "_id" : 2, "name" : "Sam Small", "age" : 23 }
    { "_id" : 3, "name" : "Mindy Medium", "age" : 23 }
    

    So, to do the updates you asked about in your question in the shell, I'd use a for loop but dispense with the db.eval in favor of multiple calls to db.people.update()

    > updates = [
        [{ "age": "Thirty Two" }, { "$set" : { "age" : 32 } }],
        [{ "age": "Fifty-Five" }, { "$set" : { "age" : 55 } }],
        [{ "age": "Twenty" }, { "$set" : { "age" : 20 } }]
    ]
    > updates.forEach(function(pair) {
        db.people.update(pair[0], pair[1])
    })
    

    If you have hundreds of updates and are using MongoDB 2.6 or later, look into bulk operations. There's more information in the db.collection.update() docs.