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

bulkSave bug: "TypeError: path.indexOf is not a function" #11071

Closed
shyrik13 opened this issue Dec 10, 2021 · 8 comments · Fixed by #11186
Closed

bulkSave bug: "TypeError: path.indexOf is not a function" #11071

shyrik13 opened this issue Dec 10, 2021 · 8 comments · Fixed by #11186
Assignees
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@shyrik13
Copy link

Report a bug

Current behavior
Using bulkSave method returns such error after Documents modified:

TypeError: path.indexOf is not a function
 at model.isSelected (/var/www/project/corejs/node_modules/mongoose/lib/document.js:2230:12)
 at model.Model.$__version (/var/www/project/corejs/node_modules/mongoose/lib/model.js:842:13)
 at /var/www/project/corejs/node_modules/mongoose/lib/model.js:3710:16
 at Array.reduce (<anonymous>)
 at Function.buildBulkWriteOperations (/var/www/project/corejs/node_modules/mongoose/lib/model.js:3681:37)
 at Function.Model.bulkSave (/var/www/project/corejs/node_modules/mongoose/lib/model.js:3606:32)
 at PairModel.bulkSaveTest (/var/www/project/corejs/Model/PairModel.js:282:37)
 at processTicksAndRejections (internal/process/task_queues.js:97:5)

Steps to reproduce.

const mongoose = require('mongoose');

let pairSchema = new mongoose.Schema({
           ask: Number,
           bid: Number,
           last: Number,
           code: String
       }, { versionKey: false });

const model = mongoose.model('pairs', pairSchema);

async function test() {
    let pairs = await model.find({});

    // modify all documents
    for (let p of pairs) {
        p.code = "test"
    }
    
    // !!! "TypeError: path.indexOf is not a function" occurs here
    let res = await model.bulkSave(pairs);
}

test();

Expected behavior
Takes an array of documents, gets the changes and inserts/updates documents in the database according to whether or not the document is new, or whether it has changes or not.

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

NodeJS: v13.14.0
Mongoose: ^6.1.1
MongoDB: Docker image: mongo:4.2

@vkarpov15 vkarpov15 added this to the 6.1.4 milestone Dec 12, 2021
@IslandRhythms IslandRhythms added the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label Dec 14, 2021
@IslandRhythms
Copy link
Collaborator

const mongoose = require('mongoose');

let pairSchema = new mongoose.Schema({
           ask: Number,
           bid: Number,
           last: Number,
           code: String
       }, { versionKey: false });

const model = mongoose.model('pairs', pairSchema);

async function test() {
    await mongoose.connect('mongodb://localhost:27017/', {useNewUrlParser: true,
        useUnifiedTopology: true,});
        await mongoose.connection.dropDatabase();
    let pairs = await model.find({});

    // modify all documents
    for (let p of pairs) {
        p.code = "test"
    }
    
    // !!! "TypeError: path.indexOf is not a function" occurs here
    let res = await model.bulkSave(pairs);
    console.log('done');
}

test();

@vkarpov15 vkarpov15 removed this from the 6.1.4 milestone Dec 15, 2021
@shyrik13
Copy link
Author

Hi,
There is still issue.
I log path variable in isSelected method and it's value is false.

image

Logged issue

image

Can you provide NodeJS, MongoDB, Mongoose versions you are using?
Maybe that is the case...

@IslandRhythms
Copy link
Collaborator

same version of mongoose, v 16 of node

@shyrik13
Copy link
Author

shyrik13 commented Dec 23, 2021

@IslandRhythms
We made test with yours code snipped and we have question.
Why there is a await mongoose.connection.dropDatabase(); line that actually clear all collections and bulk save does nothing.

Please try our new test without await mongoose.connection.dropDatabase();.

File TestModel.js

'use strict';
const mongoose = require('mongoose');

/**
 * @singleton - use create method to get instance.
 * Mongoose model can't be compiled multiple times, therefor singleton is used.
 */
class TestModel {
    static _instance;
    _model;

    /**
     * @private
     */
    constructor() {}

    static create() {
        if (this._instance) {return this._instance;}
        this._instance = new this();

        let pairSchema = new mongoose.Schema({
            name: String,
            timestamp: String
        }, { versionKey: false });

        this._instance._model = mongoose.model('test', pairSchema);

        return this._instance;
    }

    async insertTests() {

        const tests = [
            {name: 't1', timestamp: Date.now()},
            {name: 't2', timestamp: Date.now()},
            {name: 't3', timestamp: Date.now()},
            {name: 't4', timestamp: Date.now()},
        ];

        try {
            return this._model.insertMany(tests, {
                ordered: false
            });
        }
        catch (err) {
            throw new Error(`${this.constructor.name} insertMany: ${err}`);
        }
    }

    async all() {
        return await this._model.find({});
    }

    async bulkSaveTest(tests) {
        for (let p of tests) {
            p.timestamp = Date.now();
        }

        // !!! "TypeError: path.indexOf is not a function" occurs here
        let res = await this._model.bulkSave(tests);
        console.log('saved');
    }

}

module.exports = TestModel;

File app.js

const testModel = require('./TestModel').create();

async function test() {
    await testModel.insertTests();
    let tests = await testModel.all();
    await testModel.bulkSaveTest(tests);
}

test();

@vkarpov15 vkarpov15 added this to the 6.1.7 milestone Dec 27, 2021
@vkarpov15 vkarpov15 added has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Dec 27, 2021
@MinaFayez9
Copy link

Could you please add it also to TS types when fixed ?

@IslandRhythms
Copy link
Collaborator

@shyrik13 because if I don't then the modifications from the previous run are still there. When you gave the script you did not indicate that it needed to be ran twice to show an error. Are you saying that now?

@shyrik13
Copy link
Author

shyrik13 commented Jan 5, 2022

@IslandRhythms I see, then yes.
You can try to run test scripts multiple times because for me when bulkSave must work with object collection that actually in Mongo, not with empty collection, then appears "TypeError: path.indexOf is not a function".

Script from #11071 (comment) should help to reproduce mentioned error.

@IslandRhythms
Copy link
Collaborator

I ran the initial script four times with the mongoose.connection.dropDatabase() line commented out and no error.
The second script you provided reproduces the error without fail.

'use strict';
const mongoose = require('mongoose');

/**
 * @singleton - use create method to get instance.
 * Mongoose model can't be compiled multiple times, therefor singleton is used.
 */
class TestModel {
    static _instance;
    _model;

    /**
     * @private
     */
    constructor() {}

    static create() {
        if (this._instance) {return this._instance;}
        this._instance = new this();

        let pairSchema = new mongoose.Schema({
            name: String,
            timestamp: String
        }, { versionKey: false });

        this._instance._model = mongoose.model('test', pairSchema);

        return this._instance;
    }

    async insertTests() {

        const tests = [
            {name: 't1', timestamp: Date.now()},
            {name: 't2', timestamp: Date.now()},
            {name: 't3', timestamp: Date.now()},
            {name: 't4', timestamp: Date.now()},
        ];

        try {
            return this._model.insertMany(tests, {
                ordered: false
            });
        }
        catch (err) {
            throw new Error(`${this.constructor.name} insertMany: ${err}`);
        }
    }

    async all() {
        return await this._model.find({});
    }

    async bulkSaveTest(tests) {
        for (let p of tests) {
            p.timestamp = Date.now();
        }

        // !!! "TypeError: path.indexOf is not a function" occurs here
        let res = await this._model.bulkSave(tests);
        console.log('saved');
    }

}

const testModel = TestModel.create();

async function test() {
    await mongoose.connect('mongodb://localhost:27017/', {useNewUrlParser: true,
    useUnifiedTopology: true,});
    await mongoose.connection.dropDatabase();
    await testModel.insertTests();
    let tests = await testModel.all();
    await testModel.bulkSaveTest(tests);
}

test();

@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Jan 5, 2022
@vkarpov15 vkarpov15 modified the milestones: 6.1.7, 6.1.6 Jan 5, 2022
@IslandRhythms IslandRhythms linked a pull request Jan 6, 2022 that will close this issue
vkarpov15 added a commit that referenced this issue Jan 9, 2022
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.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants