Automattic / Automattic/mongoose

Bug: Setters on virtuals are not called on findOneAndUpdate

Open
#8,804 6 comments 1 reaction 0 assignees View on GitHub
discussion
Dominant language
JavaScript
Stars
27.5k
Forks
4k
Avg merge
2d 5h
Merged PRs (30d)
32

Description

**Do you want to request a *feature* or report a *bug*?**
Bug.

**What is the current behavior?**
On `findOneAndUpdate` the setters of normal fields get called as expected, but the setters for virtuals don't.

**If the current behavior is a bug, please provide the steps to reproduce.**
I've built a minimal repo to reproduce the bug: https://github.com/TiKo98/mongoose-bug
To start, run `npm install` and `npm start`.

Here is the important code:
```
const mongoose = require('mongoose');
const { Schema } = mongoose;

const testSchema = new Schema({
field: { type: String, set: v => { console.log('set field'); return v }}
})

testSchema.virtual('virtual').set(v => {
console.log('set virtual');
return v;
});

const Test = mongoose.model('test', testSchema);

const worksWell = new Test({
field: "Hello World",
virtual: "It's me."
})
worksWell.save(); // -> "set field", "set virtual"

const server = http.createServer( async (req, res) => {
await Test.findOneAndUpdate({field: "Hello World"}, {field: "Invokes setter", virtual: "Won't invoke setter"}); // -> "set field", "set field"

res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
```

**What is the expected behavior?**
I would expect the setter of the virtual to be called as well.

**What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.**
`"mongoose": "^5.9.9",
"node": "^13.13.0"`

**More information**
You see that I didn't connect the example code to any MongoDB. But that doesn't change the behavior of this bug.

A little research revealed that mongoose 4.10 introduced the runSettersOnQuery option. Then issue #5340 stated, that this should be enabled by default and that the option would be removed by mongoose v5. This seems to have worked for normal fields but not for virtuals.

This is my first contribution to open-source projects, so I hope to have provided useful information ;)

Contributor guide

Open the contributing guide

Research direction

Run npm install and npm start in the linked minimal repository to reproduce the difference between normal-field and virtual setters. Trace Mongoose's findOneAndUpdate update-processing path, then verify that the virtual setter is invoked as expected and add regression coverage for the reported behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
backend, database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.