简体   繁体   中英

MongoDB getIndex / amend TTL Index

I'm using MongoDB and Java. I have the Mongo 3.0.1 java driver. I have created a collection, which has a TTL index on it with an expireAfter property. If I try to amend that value then the code will error with:

'exception: Index with name: created_1 already exists with different options'

I therefore want to check if the index exists, and check the expireAfter attribute of the index, before deciding whether to drop the index and create a new version of it.

The MongoCollection object only has listIndexes method, which return a collection. What is the best way to get the index, and check the expireAfter property?

Here is the code that creates the index in the first place. The problem occurs when I change the value of the EXPIRATION_DAYS constant and rerun the code:

private static final Long EXPIRATION_DAYS = Long.valueOf(10);

....

final IndexOptions options = new IndexOptions();
options.expireAfter(EXPIRATION_DAYS, TimeUnit.DAYS);
database.getCollection(errors).createIndex(new BasicDBObject("created", 1), options); 

You cannot update indexes in MongoDB. You have to drop the existing index first and then recreate it with different options.

I suggest you create the index with a specific name. This way you can iterate over the existing indexes and drop the index in question before creating it again.

private static final Long EXPIRATION_DAYS = Long.valueOf(10);
private static final String INDEX_NAME = "myIndex";

[...]

MongoCollection<Document> errorsCollection = database.getCollection(errors);
ListIndexesIterable<Document> indexes = errorsCollection.listIndexes();
for (Document index : indexes) {
    if (index.getString("name").equals(INDEX_NAME) && index.getLong("expireAfterSeconds") != TimeUnit.SECONDS.convert(EXPIRATION_DAYS, TimeUnit.DAYS)) {
        errorsCollection.dropIndex(INDEX_NAME);
    }
}

IndexOptions options = new IndexOptions()
    .name(INDEX_NAME)
    .expireAfter(EXPIRATION_DAYS, TimeUnit.DAYS);
errorsCollection.createIndex(new Document("created", 1), options);

According to mongoDB docs the only way to modify an existing index is to drop it and create again.

If you want to get a specific index without looping over the list you can use findOne on the system.indexes collection:

DBObject index = database.getCollection("system.indexes")
                         .findOne(new BasicDBObject("name", "created_1"));

If no such index exists then you'll get null otherwise you will be able to read the expireAfterSeconds property - seconds, not days.

According to the MongoDB docs , you've been able to run a command in the Mongo shell like the following since v2.2:

db.runCommand({collMod: "<collection-name>",
               index : { keyPattern: { "<indexed-field>": 1 },
                         expireAfterSeconds: <new-value> }})

Translating that to use the MongoDB Java driver , you get:

Document collModCmd =
  Document.parse("{collMod: '<collection-name>', " +
                 " index : { keyPattern: {'<indexed-field>': 1}, " +
                 "           expireAfterSeconds: <new-value> }}");
Document commandResult = db.runCommand(collModCmd);

Seems to work fine for me on a test collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM