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

Populating ObjectId that has No Document Match Should Be Null - Breaking Change from Older Versions #9913

Closed
dbronin opened this issue Feb 10, 2021 · 0 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue
Milestone

Comments

@dbronin
Copy link

dbronin commented Feb 10, 2021

Do you want to request a feature or report a bug?
Reporting a bug

What is the current behavior?
Currently, if populating an ObjectId that does not resolve to an actual document, in certain cases, the results still have the ObjectId instead of null.

If the current behavior is a bug, please provide the steps to reproduce.

'use strict'

const util = require('util')
const mongoose = require('mongoose')

mongoose.set('useFindAndModify', false)

const { Schema } = mongoose

run().catch(err => console.log(err))

async function run() {
await mongoose.connect('mongodb://localhost:27017/test', {
        useNewUrlParser: true,
        useUnifiedTopology: true
    })

    const Books = mongoose.model('books', new Schema({name: String, tags: [{type: Schema.Types.ObjectId}]}))
    const Tags = mongoose.model('tags', new Schema({authors: [{author: Schema.Types.ObjectId, num: Number}]}))
    const Authors = mongoose.model('authors', new Schema({name: String}))

    const anAuthor = new Authors({name: 'Author1'})
    await anAuthor.save()

    const aTag = new Tags({authors: [{author: anAuthor.id, num: 0}, {author: mongoose.Types.ObjectId(), num: 1}]})
    await aTag.save()

    const aBook = new Books({name: 'Book1', tags: [aTag.id]})
    await aBook.save()

    const aggregateOptions = [
        { $match: {
            name: {$in: [aBook.name]}
        }},
        { $lookup: {
            from: "tags",
            localField: "tags",
            foreignField: "_id",
            as: "tags"
        }}
    ]
    const allBooks = await Books.aggregate(aggregateOptions).exec()

    console.log('books = ' + util.inspect(allBooks, false, null, true))

    //after the find, the result is the following books array:
    /*const books = books = [{
        _id: 60233aaf5b270f34b3c9eb7d,
        tags: [{
            _id: 60233aaf5b270f34b3c9eb7a,
            authors: [{
                _id: 60233aaf5b270f34b3c9eb7b,
                author: 60233aaf5b270f34b3c9eb78, //this author id points to an actual doc
                num: 0
            }, {
                _id: 60233aaf5b270f34b3c9eb7c,
                author: 60233aaf5b270f34b3c9eb79, //this author id does NOT point to an actual doc
                num: 1
            }]
        }],
        name: 'Book1'
    }]*/
 
    //we want to populate author
    const populateOptions = [{
            path: 'tags.authors.author',
            model: 'authors',
            select: '_id name'
    }]
 
    const populatedBooks = await Books.populate(allBooks, populateOptions)

    console.log('populatedBooks = ' + util.inspect(populatedBooks, false, null, true))

    //populateBooks now looks like this:
    /*populateBooks = [{
        _id: 60233aaf5b270f34b3c9eb7d,
        tags: [{
            _id: 60233aaf5b270f34b3c9eb7a,
            authors: [{
                _id: 60233aaf5b270f34b3c9eb7b,
                author: { _id: 60233aaf5b270f34b3c9eb78, name: 'Author1' },
                num: 0
            },{
                _id: 60233aaf5b270f34b3c9eb7c,
                author: 60233aaf5b270f34b3c9eb79, //*this should NOT be an objectId - it should be null (and it was in 5.2.10)
                num: 1
            }],
        }],
        name: 'Book1'
    }]*/
    
    await mongoose.connection.dropDatabase()
}

What is the expected behavior?
After the populate, any ObjectIds that did not resolve to a document should be null.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Node.js: 12.18.3
MongoDB: 3.6.21
Mongoose: 5.11.15

Thank you!

@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Feb 11, 2021
@vkarpov15 vkarpov15 added this to the 5.11.17 milestone Feb 12, 2021
vkarpov15 added a commit that referenced this issue Feb 16, 2021
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. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue
Projects
None yet
Development

No branches or pull requests

3 participants