Automattic / mongoose

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

Model.updateOne not sending query to db #7171

Closed govindrai closed 5 years ago

govindrai commented 5 years ago

Using the latest Mongoose 5.3.5 and node 8.11.4.

Here's some code that I am using to send updateOne commands:

...
const proms = inBucketsUnchanged.map(bucketName => {
      console.log(this.location);
      console.log(typeof this._id);
      return BucketMember.updateOne(
        { userId: this._id },
        { preferenceHash: this.preferenceHash, location: this.location }
      );
});
console.log(proms); // printed below
return Promise.all(proms);
...

All other mongoose calls are working perfectly. this refers to a User document. Values are valid as can be seen from an example query.

Here's the query actually printed out. I have my debugging turned on and I can't find mongoose's debug statement printed for this operation, neither is anything changing in the nothing changes in the DB

Query {
    _mongooseOptions: {},
    _transforms: [],
    mongooseCollection: 
     NativeCollection {
       collection: [Object],
       opts: [Object],
       name: 'male_25_female_20',
       collectionName: 'male_25_female_20',
       conn: [Object],
       queue: [],
       buffer: false,
       emitter: [Object] },
    model: 
     { [Function: model]
       hooks: [Object],
       base: [Object],
       modelName: 'male_25_female_20',
       model: [Function: model],
       db: [Object],
       discriminators: undefined,
       '$appliedMethods': true,
       '$appliedHooks': true,
       schema: [Object],
       collection: [Object],
       Query: [Object],
       '$__insertMany': [Function],
       '$init': [Object],
       '$caught': true },
    schema: 
     Schema {
       obj: [Object],
       paths: [Object],
       aliases: {},
       subpaths: {},
       virtuals: [Object],
       singleNestedPaths: [Object],
       nested: {},
       inherits: {},
       callQueue: [],
       _indexes: [Array],
       methods: {},
       methodOptions: {},
       statics: {},
       tree: [Object],
       query: {},
       childSchemas: [Array],
       plugins: [Array],
       '$id': 10,
       s: [Object],
       _userProvidedOptions: {},
       options: [Object],
       '$globalPluginsApplied': true,
       _requiredpaths: [Array] },
    op: 'updateOne',
    options: {},
    _conditions: { userId: 5bceb25d3edab356a9a7d4b8 },
    _fields: undefined,
    _update: 
     { preferenceHash: '616e02629a6ee281ae6f7875acc9d035c029a0f69eba5c36fcf4c49b0b6925df',
       location: [Object] },
    _path: undefined,
    _distinct: undefined,
    _collection: NodeCollection { collection: [Object], collectionName: 'male_25_female_20' },
    _traceFunction: undefined,
    '$useProjection': true }

Currently having to find the document and then update it using document.prototype.updateOne

...
      return BucketMember.findOne({ userId: this._id }).then(bucketMember => {
        return bucketMember.updateOne({
          preferenceHash: this.preferenceHash,
          location: this.location,
        });
      });
...
lineus commented 5 years ago

@govindrai when you return Promise.all(proms, are you awaiting the response? e.g. await myFunctionThatReturnsPromiseDotAll();?

If so, can you create a complete example like the one below that demonstrates your expectations and shows the failure?

7171.js

#!/usr/bin/env node
'use strict';

const assert = require('assert');
const mongoose = require('mongoose');
const { Schema, connection} = mongoose;
const DB = '7171';
const URI = `mongodb://localhost:27017/${DB}`;
const OPTS = { family: 4, useNewUrlParser: true };

const schema = new Schema({
  name: String
});

const Test = mongoose.model('test', schema);

const tests = '0123456789'.split('').map(d => ({ name: `test${d}`}));

function myFunctionThatReturnsPromiseDotAll(docs) {
  const proms = docs.map(d => {
    return Test.updateOne({ _id: d._id }, { name: `${d.name}_take2` });
  });
  return Promise.all(proms);
}

async function test() {
  const updated = await Test.find({});
  assert.strictEqual(updated.filter(u => /_take2/.test(u.name)).length, 10);
}
async function run() {
  await mongoose.connect(URI, OPTS);
  await connection.dropDatabase();
  const docs = await Test.create(tests);
  assert.ok(docs);
  assert.strictEqual(docs.length, 10);
  await myFunctionThatReturnsPromiseDotAll(docs);
  await test();
  console.log('All Assertions Pass.');
  await connection.close();
}

run();

Output:

issues: ./7171.js
All Assertions Pass.
issues:
govindrai commented 5 years ago

@lineus sincerely apologize for wasting your time.. The reason these calls were never making it was because I was passing an array of promises into an array and passing that final array into a Promise.all call (i.e. Promise.all([[arrayOfPromises],[arrayOfPromises]...)). And so Promise.all was resolving the arrays immediately.. 🤦‍♂️

However, thank you for providing that example file..I really like how you have formatted your test in a new database. I will use this as a template to test my assertions in the future before raising an issue.

Super appreciate your response, nonetheless.

lineus commented 5 years ago

@govindrai no apologies necessary. I'm glad you got it sorted out!