SoftInstigate / restheart

Rapid API Development with MongoDB
https://restheart.org
GNU Affero General Public License v3.0
807 stars 171 forks source link

findAndModify #271

Closed trapperkeeper closed 6 years ago

trapperkeeper commented 6 years ago

There doesn't seem to be a way to update a value and read the updated value in the same operation. What I want to do is increment a sequence and return the new value, in one operation. I am trying to create an auto-incrementing field and I want to ensure that each incremented value is read only once. I generated a sequence in MongoDB, and a function that increments and returns the value, but this function is not accessible via RestHeart. I know that MongoDB has a findAndModify function that will modify a values and return it in one op, but there doesn't seem to be a RestHeart wrapper for this. Is there any way to force an update operation (PATCH) to return the new value? Is there any other way of doing this in RestHeart?

ujibang commented 6 years ago

To achieve this you can create a transformer that injects the new value in The PATCH response

trapperkeeper commented 6 years ago

Just to clarify the approach you suggest, can you fill in a bit of detail? Would I need to create a MongoClient, within the transformer, and perform a separate read operation? If so, wouldn't it still be a two operation process? Or do I create a client and do a findAndModify? If the latter, can I then prevent the increment that the request would have done (without my transformer)?

ujibang commented 6 years ago

you can get the updated document from the transformer without an additional query.

have a look at the code of the example SnooperHook, specifically at this point

if (context.getDbOperationResult() != null) {
            BsonDocument newData = context
                    .getDbOperationResult()
                    .getNewData();
}

Basically the method context.getDbOperationResult().getNewData()should return the updated document. In it you will find your auto-incremented value.

trapperkeeper commented 6 years ago

Excellent, I'll give it a try. Thank you very much!

trapperkeeper commented 6 years ago

Thanks again for your help. I was able to get it working using the built-in transformer org.restheart.metadata.transformers.WriteResultTransformer. For anyone else who stumbles across this thread, I have a collection called 'sequences'. Documents in the collection store the next available number in a field called 'sequence_value'. I put a WriteResultTransformer on the collection and now get oldData and newData in the write (PATCH) response when I do an $inc of said value.