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

No indexes created when connected to a replica set with readPreference specified #11976

Closed
2 tasks done
CLaszlo opened this issue Jun 22, 2022 · 7 comments
Closed
2 tasks done
Assignees
Milestone

Comments

@CLaszlo
Copy link

CLaszlo commented Jun 22, 2022

Prerequisites

  • I have written a descriptive issue title
  • I 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

  1. Start a replicaSet (potentially update the script below with the node ports)
  2. Run the code below with no args
  3. 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.

@CLaszlo CLaszlo changed the title No indexes created when connecting to a replica set with readPreference specified No indexes created when connected to a replica set with readPreference specified Jun 22, 2022
@vkarpov15 vkarpov15 added this to the 6.4.2 milestone Jun 25, 2022
@emrsin
Copy link

emrsin commented Dec 27, 2022

This bug still happens if the readPreference is different of primary and primaryPreferred.
The only way that I found to solve this issue temporaly was using the sugestion shared by the @CLaszlo where I set autoIndex as true in the schema options.

@vkarpov15
Copy link
Collaborator

@emrsin can you please clarify the issue you're seeing?

@emrsin
Copy link

emrsin commented 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
Copy link
Collaborator

@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
Copy link

@CLaszlo @emrsin Try syncing indexes await mongoose.syncIndexes(); once connection is established

@danopia
Copy link

danopia commented Jul 28, 2023

MongoDB server doesn't allow any writes on secondaries, so trying to send a createIndex to a secondary would fail.

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 with readPreference=secondaryPreferred.

@vkarpov15
Copy link
Collaborator

@danopia that's fair, it looks like you can use createIndex() with readPreference=secondaryPreferred, assuming that you are connected to the primary. Sending createIndex() to a secondary will still fail, but it looks like the MongoDB driver ignores readPreference=secondaryPreferred for createIndex() now.

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

5 participants