Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.96k stars 3.84k forks source link

Odd behavior between populate and streamming #1990

Closed duran closed 5 years ago

duran commented 10 years ago

When you try to stream a "populated query" you can end not with a document but a string. An example of a populated document:

{ text: 'text',
  id: '{ _id: 533c41df4a4edfee13762a03, __v: 0, numbers: [ 1, 2, 3 ] }',
  _id: 533c41df4a4edfee13762a04,
  __v: 0 }

And this is reproducible code of this conduct:

var mongoose    = require('mongoose');

mongoose.connect('mongodb://localhost');

var schema1 = new mongoose.Schema({
    "numbers": [Number]
}, {
  'strict': true
});

var schema2 = new mongoose.Schema({
    "id": String,
    "text": String
}, {
  "strict": true
});

var Model1 = mongoose.model('Model1', schema1);
var Model2 = mongoose.model('Model2', schema2);

(new Model1({ numbers: [1,2,3] })).save(function(e, r){
    if(e) throw e;

    (new Model2({ text: 'text', id: r._id.toString() }))
    .save(function(e, r){
        if(e) throw e;

        Model2
        .find()
        .populate({ path: 'id', model: Model1})
        .stream()
        .on('data', function(doc){
            console.log(doc);
            console.log('typeof doc.id =', typeof doc.id)
        })
    });
});

Please close the issue if this is not a bug but intended.

Regards, Bruno.

rybnik commented 10 years ago

:+1:

duran commented 10 years ago

If someone is facing this problem too, a workaround is to set the .lean option in the query:

      Model
        .find()
        .populate({ path: 'id', model: OtherModel})
        .lean()
        .stream()
vkarpov15 commented 5 years ago

Query#stream() was removed in 5.0.0 in favor of Query#cursor(), and with Query#cursor() the below code works as intended:

var mongoose    = require('mongoose');

mongoose.set('debug', true);
mongoose.connect('mongodb://localhost');

var schema1 = new mongoose.Schema({
    "numbers": [Number]
}, {
  'strict': true
});

var schema2 = new mongoose.Schema({
    "id": String,
    "text": String
}, {
  "strict": true
});

var Model1 = mongoose.model('Model1', schema1);
var Model2 = mongoose.model('Model2', schema2);

(new Model1({ numbers: [1,2,3] })).save(function(e, r){
    if(e) throw e;

    (new Model2({ text: 'text', id: r._id.toString() }))
    .save(function(e, r){
        if(e) throw e;

        Model2
        .find()
        .populate({ path: 'id', model: Model1})
        .cursor()
        .on('data', function(doc){
            console.log(doc);
            console.log('typeof doc.id =', typeof doc.id) // object
        })
    });
});