Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs about Document#$where #10583

Closed
spaiz opened this issue Aug 18, 2021 · 2 comments
Closed

Docs about Document#$where #10583

spaiz opened this issue Aug 18, 2021 · 2 comments
Labels
docs This issue is due to a mistake or omission in the mongoosejs.com documentation
Milestone

Comments

@spaiz
Copy link

spaiz commented Aug 18, 2021

Hey. I have some legacy system, where the pattern model.findByID() -> change -> model.save() heavily used.

We have concurrency issues, and we decided to try to implement optimistic concurrency manually. I know the last mongoose version supports out of the box the optimisticConcurrency, but we cannot upgrade. And even if I could, I wouldn't use a single version flag because it will stress our system. We have too many fields on the object. that updated too often, even if they are not really related. As result, it will affect each update we have, including UI, and will make our life worse.

The idea is to introduce some additional field, like fooVersion, and increments it only when some specific fields were changed. I want to secure only a specific set of fields from concurrency issues. Don't care about other stuff for now...

This was my idea (pseudo):

ModelSchema.pre('save', function (next) {
	var self = this;

       if (isUpdate) {
             const currentFooFieldVersion = self..... get value loaded from db;
      
              // if some fields modified, I increase the version
	      if (self.isModified('fooField')) {
		      self.fooFieldVersion = new Date().getTime();
	      }
      
              // add the original version value to the internal query object
	      const conditions = self.Query();
	      conditions.set({
	         fooFieldVersion: currentFooFieldVersion.
	      });
	      
	      self._conditions = conditions;
        }
	next();
});

I want to force the mongoose to generate under the hood the update with query (I assume it uses updateOne under the hood)

.updateOne({ _id: ObjectId("......."), fooFieldVersion: currentFooFieldVersion }

Then I wanted to capture results, and if zero docs were updated, throw concurrency error to the business flow, so the client can retry.

Cannot find any way to access the query from the pre('save') hook.

Also thinking how can I safely refactor code to use updateOne() explicitly instead of .save(), without refactoring the whole business logic. Do we have any API to force mongoose model provide me the "diff" it will use on save() so I can take it, and put manually to updateOne()?

Thanks!

p.s.
We use mongoose: v5.6.7

@spaiz spaiz changed the title Accessing Query() on pre('save') hook to implement optimistic concurrency Accessing Query() on pre('save') hook to implement optimistic concurrency control Aug 18, 2021
@IslandRhythms IslandRhythms added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Aug 18, 2021
@spaiz
Copy link
Author

spaiz commented Aug 18, 2021

OK. Looks like I found the way to do it. Looks like magic to me, cause self.$where is undefined when I try to debug, but it still works when I explicitly create it like that.

		self.$where = {
			'listingAssignVersion': currentListingAssignVersion,
		};

Not sure how safe it is :/

Does anyone know about any documentation related to it?

@vkarpov15
Copy link
Collaborator

We don't have good documentation for this.$where currently, but you're right that $where is our recommended way to implement custom optimistic concurrency plugins, see #4004. The only notes we have are in our changelog: https://github.com/Automattic/mongoose/blob/master/History.md#480--2017-01-28 and #4004. this.$where will be undefined by default because it's a property that we've added to allow users to modify the query filter that save() uses.

We'll keep this open to make a note about $where.

@vkarpov15 vkarpov15 added docs This issue is due to a mistake or omission in the mongoosejs.com documentation and removed help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary labels Aug 23, 2021
@vkarpov15 vkarpov15 added this to the 5.13.8 milestone Aug 23, 2021
@vkarpov15 vkarpov15 changed the title Accessing Query() on pre('save') hook to implement optimistic concurrency control Docs about Document#$where Aug 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This issue is due to a mistake or omission in the mongoosejs.com documentation
Projects
None yet
Development

No branches or pull requests

3 participants