info
Morphium and Indices
Defining Indices
First of all, you usually do not need to care about Indices in Mongodb, just define it in your entity code:
´´´java @Entity public class MyEntity { @Id private MorphiumId id; @Index private String myIndexedString; @Index(decrement = true) private Integer aNumber; } ´´´
There are more options for defining indices, please consult the morphium documentation for details.
Index creation
As already mentioned, Morphium usually takes care of creation of indices following a simple rule:
- when writing, check if the collection already exists, if not, create indexes
- do nothing if collection is already there
The reason being, that if you have big collections, it might cause problems to create new indices when writing - it might affect the system. But if the collection does not exist, this is quite a small operation.
But there's a catch: this check costs time, every write morphium checks, if the collection exists.
You can change this behaviour by switching automatic index creation off in MorphiumConfig config.setAutoIndexAndCappedCreationOnWrite(false)
.
Starting with morphium V4.2.3, you can also have morphium check those indices only on startup.
morphiumConfig.setIndexCappedCheck(IndexCappedCheck.WARN_ON_STARTUP)
This will issue a warning in log, if an index for an entity is missing. There are more options, you can choose from:
NO_CHECK
: do not check, if indices matchWARN_ON_STARTUP
: check indices for all Entities on startup/connect. This will slow down startup depending on your code.CREATE_ON_WRITE_NEW_COL
: create missing indices, when writing to a new collection (Default behaviour)CREATE_ON_STARTUP
: check for indices only once when starting up / connecting to mongo.
Hint: There is no option to warn on write, this would slow down mongodb access significantly!
Warnings for missing indices look like this:
Collection 'person' for entity 'de.caluga.test.mongo.suite.TextIndexTest$Person' does not exist.
Capped collections
Morphium does combine handles the capped status of collection together with indices. That means, if the collection does not exists, but @Capped-Annotation is used, the collection is created capped. This is done together with the indices, so if you check those, capped information is also checked. Depending on settings, the collection might also be automatically converted to a capped collection!
programmatically creating indices
The easiest way to create indices is, to call the method ensureIndicesFor(ENTITYCLASS)
.
This will create all indices, that are defined in code for this entity (using the @Index annotation).
If you also want to ensure, the corresponding collection is capped, if defined accordingly, call morphium.ensureCapped(ENTITYCLASS)
.
Both methods will not create indices or capped collections, if no index is defined in code. But it will call ensureIndex
on mongodb.
Hint: when an index is created for a non existend collection, there will be an empty collection in mongodb.
But you can also create indices more manually:
´´´javak
public
the Index map contains the Document that describes the index (similar as directly in mongodb) and the options are the corresponding options for this index. e.g.
´´´java morphium.ensureIndex(UncachedObject.class, "uncached_object",Utils.getMap("counter",1),Utils.getMap("unique","true"),null); ´´´
get Information about missing indices
In order to get just the information on missing indices for a specific Entity (or all of them), you can get this information starting with MongoDB V4.2.3: ´´´java Map<Class<?>, List<Map<String, Object>>> missing = morphium.checkIndices(); ´´´
returns a Map with the entity class as key and a list of missing Index definitions as value. you can use this map to manually create an index:
´´´java Map<Class<?>, List<Map<String, Object>>> missing = morphium.checkIndices(); morphium.ensureIndex(EntObject.class,missing.get(EntObject.class).get(0)); ´´´
ATTENTION:
- the
checkIndices()
also adds missing capped information to the result map! checkIndices()
runs through the whole classpath, which can take some milliseconds, if you want to reduce the load, you can usecheckIndices(filter)
, and filter classes according to your needs:checkIndices(classInfo -> !classInfo.getPackageName().startsWith("de.caluga.morphium"));
conclusion
The performance of Databases strongly depends on proper creation of indices. With morphium you can define them all in code, which reduces the need to know, how to create indices in Mongodb manually for java engineers and hence improves performance.