67

Is there a command that i can use via javascript in mongo shell that can be used to check if the particular index exists in my mongodb. I am building a script file that would create indexes. I would like that if I run this file multiple number of times then the indexes that already exists are not recreated.

I can use db.collection.getIndexes() to get the collection of all the indexes in my db and then build a logic to ignore the ones that already exists but i was wondering if there is command to get an index and then ignore a script that creates the index. Something like:

If !exists(db.collection.exists("indexname")) 
{
    create  db.collectionName.CreateIndex("IndexName")
}
3
  • 11
    Calling createIndex when the index already exists is a no-op, so there's really no need to check. Commented Jan 26, 2016 at 17:08
  • 1
    Possible duplicate of ensureIndex in mongodb Commented Jan 26, 2016 at 18:59
  • 1
    @JohnnyHK: it's not a no-op if you don't have write permissions. In that case, the code will throw an error not authorized to execute command { insert: "system.indexes" ..., instead of failing silently. Commented May 9, 2019 at 20:43

7 Answers 7

91

Creating indexes in MongoDB is an idempotent operation. So running db.names.createIndex({name:1}) would create the index only if it didn't already exist.

The deprecated (as of MongoDB 3.0) alias for createIndex() is ensureIndex() which is a bit clearer on what createIndex() actually does.


Edit: Thanks to ZitRo for clarifying in comments that calling createIndex() with the same name but different options than an existing index will throw an error MongoError: Index with name: **indexName** already exists with different options as explained in this question.


If you have other reasons for checking, then you can access current index data one of two ways:

  1. As of v3.0, we can use db.names.getIndexes() where names is the name of the collection. Docs here.
  2. Before v3.0, you can access the system.indexes collection and do a find as bri describes below.
Sign up to request clarification or add additional context in comments.

7 Comments

Note that we may catch MongoError: Index with name: **indexName** already exists with different options error by doing just createIndex. So using db.collection.getIndexes() make sense sometimes. See this question for more info.
This answer is surprising. I came here because createIndex is taking upward of 30 seconds on every boot of my server (mongo 2.6). Surely it doesn't take that long to confirm whether or not the index exists?
@Thor84no 2.6 doesn't use createIndex, it uses ensureIndex docs.mongodb.com/v2.6/core/index-creation
Either way, it's taking ages and restarting the server it's no quicker. It also makes no sense that verifying the existence of the index is taking longer on my large collections than on my small ones...
I found that collection.createIndex(DBObject("_ts" -> 1), DBObject("expireAfterSeconds" -> ttl)) is not idempotent - if the expiration value is different than what's already in use, it will fail. Perhaps that's a special case that this MongoDB noob stumbled across, though.
|
23

Use db.system.indexes and search on it.

If, for example, you have an index called 'indexname', you can search for it like this:

db.system.indexes.find({'name':'indexname'});

If you need to search for that index on a specific collection,then you need to use the ns property (and, it would be helpful to have the db name).

db.system.indexes.find({'name':'indexname', 'ns':'dbname.collection'});

Or, if you absolutely hate including the db name...

db.system.indexes.find({'name':'indexname', 'ns': {$regex:'.collection$'}});

Pulling that together...

So, you're finished check would be:

if(db.system.indexes.find({name:'indexname',ns:{$regex:'.collection$'}}).count()==0) { 
    db.collection.createIndex({blah:1},{name:'indexname'}) 
}

2 Comments

Does this work on 3.4 version. I tried but it returns nothing on the console.
@SohamShetty This has been deprecated as of v3.0. You now should use db.name.getIndexes() where name is the name of your collection.
2

Using nodeJS MongoDB driver version 2.2:


const MongoClient = require('mongodb').MongoClient;

exports.dropOldIndexIfExist = dropOldIndexIfExist;
async function dropOldIndexIfExist() {
  try {
    const mongoConnection = MongoClient.connect('mongodb://localhost:27017/test');
    const indexName = 'name_1';
    const isIndexExist = await mongoConnection.indexExists(indexName);
    if (isIndexExist === true) {
      await mongoConnection.dropIndex(indexName);
    }
  } catch (err) {
    console.error('dropOldIndexIfExist', err.message);
    throw err;
  }
}

Comments

2

I've created a custom method in c# to check if the index exists, using mongo driver:

public bool IndexExists<TDocument>(
    IMongoCollection<TDocument> collection, string name)
{
    var indexes = collection.Indexes.List().ToList();
    var indexNames = indexes
        .SelectMany(index => index.Elements)
        .Where(element => element.Name == "name")
        .Select(name => name.Value.ToString());
    
    return indexNames.Contains(name);
}

Comments

1

maybe we can use something like https://docs.mongodb.com/v3.2/reference/method/db.collection.getIndexes/#db.collection.getIndexes to check if the collection have an index equal to something ?

if yes then drop and add the new one or add the new one directly

Comments

1

In my case i did as follows.

   DBCollection yourcollectionName = mt.getCollection("your_collection");
    if (yourcollectionName.getIndexInfo() == null || yourcollectionName.getIndexInfo().isEmpty()) {         
      DBObject indexOptions = new BasicDBObject();
      indexOptions.put("pro1", 1);
      indexOptions.put("pro2", 1);       
      yourcollectionName.createIndex(indexOptions, "name_of_your_index", true);
     }

Comments

0

Here is a Python 3.5+ and pymongo >= 4.1 (type hints) function that I wrote which checks to see if the index name exists (other details about the index are omitted).

from pymongo import MongoClient
from pymongo.collection import Collection

def check_collection_indexes(db: MongoClient, collection_name: str, index_name: str) -> bool:
    coll: Collection = db[collection_name]
    indexes: dict = coll.index_information()
    
    # assume false
    found = False
    # get length of the index name for substring
    l = len(index_name)
    for k in indexes.keys():
        # Substring the keys and check for match
        if k[:l] == index_name:
            found = True
            break
        else:
            found = False
    return found

If the index exists it will return True, otherwise you can use the False output to call another function that creates/recreates the indexes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.