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

virtual setter called with value undefined on populate #14285

Closed
2 tasks done
SinBirb opened this issue Jan 23, 2024 · 0 comments · Fixed by #14314
Closed
2 tasks done

virtual setter called with value undefined on populate #14285

SinBirb opened this issue Jan 23, 2024 · 0 comments · Fixed by #14314
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@SinBirb
Copy link

SinBirb commented Jan 23, 2024

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

8.1.0

Node.js version

18.18.0

MongoDB server version

7.0.5

Typescript version (if applicable)

No response

Description

Mongoose populates the virtual internally (set() is never called with the populated value), but additionally calls its setter function with the value undefined. This can lead to bad, unexpected side effects.

I'm not sure whether that is expected behavior, but if so, please advise on how we should implement the below use case.

Steps to Reproduce

Example script which outputs a person with userId: null and userType: null.

const mongoose = require('mongoose');
const uri = "mongodb://mongo1:27017/test";

async function run() {
    try {
        await mongoose.connect(uri);
        console.log("connected");

        const Schema = mongoose.Schema;
        const ObjectId = Schema.ObjectId;

        const userSchema = new Schema({
            email: String,
            name: "String",
        });

        const User = mongoose.model('User', userSchema);

        const user = await User.updateOne({
            email: "admin@example.com",
        }, {
            email: "admin@example.com",
            name: "Admin",
        }, {
            upsert: true,
        });

        const personSchema = new Schema({
            userId: ObjectId,
            userType: String,
        });

        personSchema.virtual('user', {
            ref() {
                return this.userType;
            },
            localField: "userId",
            foreignField: "_id",
            justOne: true,
        })
        .set(function (user) {
            console.log("set user:", user);
            if (user) {
                this.userId = user._id;
                this.userType = toModelName(user);
            } else {
                this.userId = null;
                this.userType = null;
            }
        });

        personSchema.pre("findOne", function () {
            this.populate("user");
        });

        const Person = mongoose.model('Person', personSchema);

        const fetchedUser = await User.findOne({ email: "admin@example.com" })

        const person = new Person({
            userId: fetchedUser._id,
            userType: "User",
        });

        await person.save();

        const fetchedPerson = await Person.findOne({ _id: person._id });

        console.log("person fetched:", fetchedPerson.toJSON({ virtuals: true }));
    } catch (e) {
        console.error(e);
    } finally {
        await mongoose.disconnect();
    }
}

run().catch(console.dir).then(() => console.log("Done"));

Expected Behavior

The populated field (i.e. person) to be populated and the setter not to be called or called with the value that was populated.

@IslandRhythms IslandRhythms added the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Jan 23, 2024
@vkarpov15 vkarpov15 added this to the 8.1.2 milestone Jan 24, 2024
@vkarpov15 vkarpov15 added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Jan 27, 2024
vkarpov15 added a commit that referenced this issue Feb 1, 2024
vkarpov15 added a commit that referenced this issue Feb 5, 2024
fix(populate): call setter on virtual populated path with populated doc instead of undefined
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
3 participants