2

Say I have an object with field state, I want to update this field, while keeping the previous value of state in previous_state field. First, I have tried to make an update with unset-rename-set:

collection.update(query, {$unset: {previous_state: ""}, $rename: {state: "previous_state"}, $set: {state: value}})

no surprise it did not work. After reading:

I am nearly convinced that I do not have a solution to perform this in a single query. So the question is what is the best practice to do it?

4
  • 1
    Can muliple users access the database? Or doe you have only one connection. Commented Dec 17, 2014 at 14:19
  • I have a single writer and multiple reader users for this collection. Does it make any difference? Commented Dec 17, 2014 at 14:23
  • That depends on how you achieve the value of the newstate. But since you only have one writer, the answer of Lombric would be the best. Commented Dec 17, 2014 at 14:26
  • Any update on this? I would agree with @InancGumus Commented Nov 17, 2021 at 6:35

2 Answers 2

1

There are various ways to do it, depending on the version of MongoDB, and they are described in this answer from another thread: https://stackoverflow.com/a/37280419/5538923 . For MongoDB 3.4+, for example, there is this query that can be put in MongoSH:

db.collection.aggregate(
[
    { "$addFields": { 
        "previous_state": { "$concat": [ "$state" ] },
        "state": { "$concat": [ "$state", " customly modified" ] } 
    }},
    { "$out": "collection" }
])

Also note that this query works only when the MongoDB instance is not sharded. When sharded (e.g., often the case in Microsoft Azure CosmosDB), the method described in that answer for MongoDB 3.2+ works, or alternatively put a new collection as destination (in the $out close), and then import the data in the original collection, after removing all the data there.

Sign up to request clarification or add additional context in comments.

Comments

0

One solution (if you've got onlty one writer) could be to trigger your update in two steps:

> var previousvalue = collection.findOne(query).state;
> collection.update(query, {$set: {"previous_state": previousvalue, "state": newstatevalue}});

2 Comments

This is not atomic and will lead to concurrency issues when more than one caller is involved (it's not scalable).
Any update on this? I would agree with @InancGumus

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.