36

Trying to create MongoDB indexes. Using the Mongoose ODM and in my schema definition below I have the username field set to a unique index. The collection and document all get created properly, it's just the indexes that aren't working. All the documentation says that the ensureIndex command should be run at startup to create any indexes, but none are being made. I'm using MongoLab for hosting if that matters. I have also repeatedly dropped the collection. What is wrong.

var schemaUser = new mongoose.Schema({
    username: {type: String, index: { unique: true }, required: true},
    hash: String,
    created: {type: Date, default: Date.now}
}, { collection:'Users' });

var User = mongoose.model('Users', schemaUser);
var newUser = new Users({username:'wintzer'})
newUser.save(function(err) {
    if (err) console.log(err);
});
Przemyslaw Kruglej
  • 8,003
  • 2
  • 26
  • 41
wintzer
  • 901
  • 2
  • 9
  • 6

9 Answers9

33

Hook the 'index' event on the model to see if any errors are occurring when asynchronously creating the index:

User.on('index', function(err) {
    if (err) {
        console.error('User index error: %s', err);
    } else {
        console.info('User indexing complete');
    }
});

Also, enable Mongoose's debug logging by calling:

mongoose.set('debug', true);

The debug logging will show you the ensureIndex call it's making for you to create the index.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • 10
    Thanks Johnny, I tried your suggestions, and while it didn't show an error, all I saw was the insert function, no ensureIndex. This lead me to think that, despite the documentation stating the autoIndex is set to true by default, that autoIndex was not on. I added `autoIndex:true` to my collection settings and it worked. Now that I have manually set `autoIndex:true` and having the debugging on shows the ensureIndex actions. – wintzer Sep 18 '12 at 02:32
  • Thanks wintzer, this helped me. I am also on MongoHQ. – ac360 Feb 05 '14 at 23:08
  • 1
    Was useful but can't fix the problem, even with setting index and unique on a field it doesn't call the ensure index – Totty.js Jun 22 '14 at 12:24
6

In my case I had to explicitly specify autoIndex: true:

const User = new mongoose.Schema({
    name: String,
    email: String,
    password: String
 },
 {autoIndex: true}
)
DannyMoshe
  • 6,023
  • 4
  • 31
  • 53
5

Mongoose declares "if the index already exists on the db, it will not be replaced" (credit).

For example if you had previous defined the index {unique: true} but you want to change it to {unique: true, sparse: true} then unfortunately Mongoose simply won't do it, because an index already exists for that field in the DB.

In such situations, you can drop your existing index and then mongoose will create a new index from fresh:

$ mongo
> use MyDB
> db.myCollection.dropIndexes();
> exit
$ restart node app

Beware that this is a heavy operation so be cautious on production systems!


In a different situation, my indexes were not being created, so I used the error reporting technique recommended by JohnnyHK. When I did that I got the following response:

E11000 duplicate key error collection

This was because my new index was adding the constraint unique: true but there were existing documents in the collection which were not unique, so Mongo could not create the index.

In this situation, I either need to fix or remove the documents with duplicate fields, before trying again to create the index.

joeytwiddle
  • 29,306
  • 13
  • 121
  • 110
2

When I hooked the index event on the model that wasn't working, I started getting an error on the console that indicated "The field 'retryWrites' is not valid for an index specification." The only place in my app that referenced 'retryWrites' was at the end of my connection string. I removed this, restarted the app, and the index rebuild was successful. I put retryWrites back in place, restarted the app, and the errors were gone. My Users collection (which had been giving me problems) was empty so when I used Postman to make a new record, I saw (with Mongo Compass Community) the new record created and the indexes now appear. I don't know what retryWrites does - and today was the first day I used it - but it seemed to be at the root of my issues.

Oh, and why did I use it? It was tacked onto a connection string I pulled from Mongo's Atlas Cloud site. It looked important. Hmm.

Newclique
  • 494
  • 3
  • 15
2

It might be solve your problem

var schema = mongoose.Schema({
speed: Number,
watchDate: Number,
meterReading: Number,
status: Number,
openTrack: Boolean,
 });
schema.index({ openTrack: 1 });
Atiq Ur Rehman
  • 230
  • 2
  • 13
  • 2
    Will this create index automatically on mongodb? I have defined the model schema and indexes like the above, but in mongodb, It doesn't create indexes, only `_id` index is there, do I need to perform some other step in order to create? – Rohit Khatri Mar 22 '19 at 10:32
  • yes it will create automatically if you use mongoose – Atiq Ur Rehman Mar 25 '19 at 07:42
2

As you can see in mongoose documentations https://mongoosejs.com/docs/guide.html#indexes, we need define schema.index to create our indexes. Take a look in code below to test:

  • Note, after update your schema restart the server to check.
const schemaUser = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
      index: true,
      unique: true,
      dropDups: true,
    },
    hash: String,
    created: {
      type: Date,
      default: Date.now,
    },
  },
  {
    autoCreate: true, // auto create collection
    autoIndex: true, // auto create indexes
  }
)
// define indexes to be create
schemaUser.index({ username: 1 })

const User = mongoose.model('Users', schemaUser)
const newUser = new Users({ username: 'wintzer' })
newUser.save(function (err) {
  if (err) console.log(err)
})
Henrique Van Klaveren
  • 1,502
  • 14
  • 24
2

Connections that set "readPreference" to "secondary" or "secondaryPreferred" may not opt-in to the following connection options: autoCreate, autoIndex.

Check your readPreference option in the mongoose connection

asafel
  • 713
  • 1
  • 7
  • 14
  • this is the correct answer for me -> https://mongoosejs.com/docs/migrating_to_6.html#autocreate-defaults-to-true – belphegor Mar 24 '22 at 10:14
1

I had this problem when writing a data import command-line utility. After execution end, some indexes were created, some were not.

The solution was to call await model.ensureIndexes() before terminating the script. It worked regardless to autoIndex option value.

valango
  • 21
  • 3
0

Сheck that the mongoose connect options do not specify :

autoIndex: false
ArkadiBernov
  • 570
  • 8
  • 13