Description
Prerequisites
- I have written a descriptive issue titleI have searched existing issues to ensure the bug has not already been reported
Mongoose version
6.2.4
Node.js version
14.16.0
MongoDB server version
5.0.9
Description
In mongoose 6.2.4, indexes defined on schema paths are not created automatically when readPreference is set on the ConnectOptions.
The problem was noticed during the upgrade from mongoose 5.10.19 to 6.2.4. New databases created after the upgrade have been missing indexes.
Potentially related to #11711 and #10631
Setting {autoIndex: true} as a schema option seems to be a workaround for now.
Steps to Reproduce
- Start a replicaSet (potentially update the script below with the node ports)
- Run the code below with no args
- Run the code below with '--no-read-pref'
The snippet sets up two databases with the same schema. The schema defines two fields, one with a unique index.
When running with no args, the assert should fail, as only the _id index is created.
When running with '--no-read-pref' the indexes are created
const assert = require('assert');
const mongoose = require('mongoose');
const rsNodes = 'localhost:30001,localhost:30002,localhost:30003';
const mainDbName = 'mainDb';
const withoutReadPref = process.argv.includes('--no-read-pref');
const testSchema = new mongoose.Schema({
field1: { type: String },
field2: { type: String, unique: true }
});
function getDbConnectionOptions() {
const dbOpts = {
readPreference: 'primaryPreferred',
replicaSet: 'rs'
};
if (withoutReadPref) {
delete dbOpts.readPreference;
}
return dbOpts;
}
function getConnectionString(dbName) {
return `mongodb://${rsNodes}/${dbName ? dbName : mainDbName}`;
}
async function registerModels(dbConn) {
const model = dbConn.model('TestSchema', testSchema);
if (!withoutReadPref) {
// When read preference is specified, the collection does not get created automatically.
await model.createCollection();
}
}
async function getDbConnection(dbName) {
const connectionOptions = getDbConnectionOptions();
const connectionString = getConnectionString(dbName);
let dbConn = mongoose.createConnection();
await dbConn.openUri(connectionString, connectionOptions);
await registerModels(dbConn);
return dbConn;
}
async function init() {
const mainDb = await getDbConnection();
const mainDbTestSchema = mainDb.model('TestSchema');
await new Promise((resolve) => setTimeout(resolve, 15000));
const mainDbIndexes = await mainDbTestSchema.listIndexes();
console.log(mainDbIndexes);
assert.strictEqual(mainDbIndexes.length, 2);
const tenantOneDb = await getDbConnection('tenantOne');
const tenantOneDbTestSchema = tenantOneDb.model('TestSchema');
await new Promise((resolve) => setTimeout(resolve, 15000));
const tenantOneIndexes = await tenantOneDbTestSchema.listIndexes();
console.log(tenantOneIndexes);
assert.strictEqual(tenantOneIndexes.length, 2);
}
init();
Expected Behavior
The indexes should be created as the documentation states that autoIndex is true by default.
Activity
[-]No indexes created when connecting to a replica set with readPreference specified[/-][+]No indexes created when connected to a replica set with readPreference specified[/+]emrsin commentedon Dec 27, 2022
This bug still happens if the
readPreference
is different ofprimary
andprimaryPreferred
.The only way that I found to solve this issue temporaly was using the sugestion shared by the @CLaszlo where I set
autoIndex
astrue
in the schema options.vkarpov15 commentedon Dec 29, 2022
@emrsin can you please clarify the issue you're seeing?
emrsin commentedon Jan 5, 2023
@vkarpov15 if I set
readPreference=secondaryPreferred
in the connection string in a database with replica set configuration the collection's index do not create automatically.vkarpov15 commentedon Jan 11, 2023
@emrsin that's expected behavior. MongoDB server doesn't allow any writes on secondaries, so trying to send a
createIndex
to a secondary would fail.privateOmega commentedon Jan 27, 2023
@CLaszlo @emrsin Try syncing indexes
await mongoose.syncIndexes();
once connection is establisheddanopia commentedon Jul 28, 2023
Is this still true? According to the MongoDB ticket NODE-2784, this error was a bug in MongoDB driver 3.6.0 which was fixed in 3.6.3. I see that mongoose is using MongoDB driver 5.7.0 nowadays.
My read is that readPreference should not interfere with write operations like
createIndex()
; clearly Mongoose is also connected to primary MongoDB nodes if it is able to update documents.Indeed, as said above,
autoIndex: true
seems to work fine withreadPreference=secondaryPreferred
.vkarpov15 commentedon Aug 1, 2023
@danopia that's fair, it looks like you can use
createIndex()
with readPreference=secondaryPreferred, assuming that you are connected to the primary. SendingcreateIndex()
to a secondary will still fail, but it looks like the MongoDB driver ignoresreadPreference=secondaryPreferred
forcreateIndex()
now.