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

.slice() before .populate() causes data loss (with test) #5737

Closed
aforty opened this issue Oct 23, 2017 · 3 comments
Closed

.slice() before .populate() causes data loss (with test) #5737

aforty opened this issue Oct 23, 2017 · 3 comments
Milestone

Comments

@aforty
Copy link

aforty commented Oct 23, 2017

What is the current behavior?
If .slice() is called before .populate() then data of the original object is lost.

Reproduce
Add this test to test/model.populate.test.js and run mocha. I took the test "populating an array of refs and fetching many" and added the line assert.equal(blogposts[0].title, 'Woot');

  it('populating an array of refs, slicing, and fetching many', function(done) {
    var db = start(),
        BlogPost = db.model('RefBlogPost', posts),
        User = db.model('RefUser', users);

    User.create({
      name: 'Fan 1',
      email: 'fan1@learnboost.com'
    }, function(err, fan1) {
      assert.ifError(err);

      User.create({
        name: 'Fan 2',
        email: 'fan2@learnboost.com'
      }, function(err, fan2) {
        assert.ifError(err);

        BlogPost.create({
          title: 'Woot',
          fans: [fan1, fan2]
        }, function(err, post1) {
          assert.ifError(err);

          BlogPost.create({
            title: 'Woot',
            fans: [fan2, fan1]
          }, function(err, post2) {
            assert.ifError(err);

            BlogPost
            .find({_id: {$in: [post1._id, post2._id]}})
            .slice('fans', [0, 5])
            .populate('fans')
            .exec(function(err, blogposts) {
              db.close();
              assert.ifError(err);

              assert.equal(blogposts[0].title, 'Woot');

              assert.equal(blogposts[0].fans[0].name, 'Fan 1');
              assert.equal(blogposts[0].fans[0].email, 'fan1@learnboost.com');
              assert.equal(blogposts[0].fans[1].name, 'Fan 2');
              assert.equal(blogposts[0].fans[1].email, 'fan2@learnboost.com');

              assert.equal(blogposts[1].fans[0].name, 'Fan 2');
              assert.equal(blogposts[1].fans[0].email, 'fan2@learnboost.com');
              assert.equal(blogposts[1].fans[1].name, 'Fan 1');
              assert.equal(blogposts[1].fans[1].email, 'fan1@learnboost.com');
              done();
            });
          });
        });
      });
    });
  });

What is the expected behavior?
The above test should pass.

Please mention your node.js, mongoose and MongoDB version.
node 8.3.0
mongod 3.2.11
mongoose 4.12.4

@aforty aforty changed the title .slice() before .populate() causes data loss .slice() before .populate() causes data loss (with test) Oct 23, 2017
@vkarpov15 vkarpov15 added this to the 4.12.5 milestone Oct 26, 2017
@vkarpov15 vkarpov15 added the bug? label Oct 26, 2017
@vkarpov15
Copy link
Collaborator

Thanks for the detailed repro instructions, will investigate ASAP 👍

vkarpov15 added a commit that referenced this issue Oct 27, 2017
@aforty
Copy link
Author

aforty commented Oct 27, 2017

Thanks for the quick fix! 🍻

@adijes
Copy link

adijes commented Nov 2, 2017

This bug still reproduce when populating one of schema fields.

Reproduce
Add this test to test/model.populate.test.js and run mocha. It will fail
on the line assert.equal(blogposts[0].title, 'Test 1');

    it('populating schema field, slicing, and fetching', function(done) {
      var BlogPost = db.model('blog-post', new Schema({
        title: String,
        user: { type: ObjectId, ref: 'user' },
        fans: [{ type: ObjectId}]
      }));
      var User = db.model('user', new Schema({ name: String }));

      User.create([{ name: 'Fan 1' }], function(error, fans) {
        assert.ifError(error);
        var posts = [
          { title: 'Test 1', user: fans[0]._id, fans: [fans[0]._id] },
        ];
        BlogPost.create(posts, function(error) {
          assert.ifError(error);
          BlogPost.
            find({}).
            slice('fans', [0, 2]).
            populate('user').
            exec(function(err, blogposts) {
              assert.ifError(error);

              assert.equal(blogposts[0].user.name, 'Fan 1');
              assert.equal(blogposts[0].title, 'Test 1');
              done();
            });
        });
      });
    });

What is the expected behaviour?
The test mentioned should pass

Please mention your node.js, mongoose and MongoDB version.
node 8.4.0
mongod 3.4.1
mongoose 4.12.6

This test passed in mongoose 4.11.13, and since version 4.11.14 stopped working

@vkarpov15 vkarpov15 reopened this Nov 2, 2017
@vkarpov15 vkarpov15 modified the milestones: 4.12.5, 4.13.1 Nov 2, 2017
vkarpov15 added a commit that referenced this issue Nov 6, 2017
Fonger added a commit to Fonger/mongoose that referenced this issue Aug 13, 2018
Fonger added a commit to Fonger/mongoose that referenced this issue Aug 13, 2018
@Fonger Fonger mentioned this issue Aug 13, 2018
Fonger added a commit to Fonger/mongoose that referenced this issue Aug 13, 2018
Fonger added a commit to Fonger/mongoose that referenced this issue Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants