mongodb-js / mongoose-autopopulate

Always populate() certain fields in your mongoose schemas
Apache License 2.0
222 stars 36 forks source link

Autopopulate Self ref #18

Closed 8eecf0d2 closed 8 years ago

8eecf0d2 commented 8 years ago

If you reference a schema from within itself autopopulate does not work. The way to do this is as follows:

var mySchema = new Schema({
    name: {type: String}
    parent: {type: String, ref: 'mySchema'}
})

Running mySchema.find({}).populate('parent').exec(function(error, docs){ ... }) works as expected, populating the document. AFAIK this is the correct way to self reference documents, weird but correct.

Adding the auto-populate key value {type: String, ref: 'mySchema', autopopulate: true} does not work, setting type: mongoose.Schema.Types.ObjectId or similar does not help or work.

I could not find any docs mentioning how to do this, all help appreciated.

vkarpov15 commented 8 years ago

The code as written won't work for numerous reasons, most notably that mongoose schemas don't have a .find() function, mongoose models do. Even if you correct that, you have a problem because mySchema docs have an _id field that's of type ObjectId, whereas parent is a string, so populate() will never match. Can you provide a more complete code sample please?

8eecf0d2 commented 8 years ago

Very sorry for the incorrect code. I can't reproduce this issue externally (anymore), so my guess is an internal error with my project.

The code below will create two docs, then query, populate and remove.

var mongoose = require('mongoose').connect('mongodb://localhost/iqnfwzcd'),
    Schema = mongoose.Schema

var modelXSchema = new Schema({
    title: {type: String, required: true},
    parent: {type: String, ref: 'modelX', autopopulate: true},
})

var modelX = mongoose.model('modelX', modelXSchema)

var _parent = new modelX({
    title: 'Parent 1'
})

_parent.save(function(error){
    console.log('parent saved:\n' + _parent)
    console.log()

    var _child = new modelX({
        title: 'Child 1',
        parent: _parent._id
    })

    _child.save(function(error){
        console.log('child saved:\n' + _child)
        console.log()

        modelX.find({}).populate('parent').exec(function(error, docs){
            console.log('populated:\n' + docs)
            console.log()
            modelX.remove({}, function(error, docs){})
        })
    })
})

Output

parent saved:
{ __v: 0, title: 'Parent 1', _id: 579ace7795db6796ab8208e4 }

child saved:
{ __v: 0,
  title: 'Child 1',
  parent: '579ace7795db6796ab8208e4',
  _id: 579ace7795db6796ab8208e5 }

populated:
{ _id: 579ace7795db6796ab8208e4, title: 'Parent 1', __v: 0 },{ _id: 579ace7795db6796ab8208e5,
  title: 'Child 1',
  parent: { _id: 579ace7795db6796ab8208e4, title: 'Parent 1', __v: 0 },
  __v: 0 }

mongoose-autopopulate seems to work with the code above, unsure why I'm having issues elsewhere.

vkarpov15 commented 8 years ago

Glad it works. Feel free to open up another issue if you figure out what's going on.