Elastic Social Manual / Version 2406.0
Table Of ContentsModel indexing
Typically, the access to Model
s is very cheap for the id property and calls to
ModelService#get(id,collection)
and very expensive for all other properties. A
ModelIndex
helps to speed up the access to other properties.
To create a ModelIndex
for the collection myobjects and the x property of all MongoDB
documents inside the collection, define a ModelIndexConfiguration
like this:
@Named public class MyObjectsModelIndexes implements ModelIndexConfiguration { @Inject private ModelIndexConfigurationBuilder builder; public Collection<ModelIndex> getModelIndexes() { return builder. configure("myobjects", "x"). build(); } }
Example 4.4. Creating a ModelIndex
This speeds up the executions of Query
s to the property x
to the same level as those for the property id
when called like this:
MyObject myObject = modelService.query("myobjects"). filter("x", EQUAL, "1234").get(MyObject.class);
Example 4.5. Create a query
Note
The creation of indexes is not enabled by default to speed up faster initial bulk loading. To enable the
creation of indexes, set mongodb.models.create-indexes
to true as described in the Configuration properties.
Note
Keep the number of indexes to an absolute minimum because they consume precious heap memory in the MongoDB.
Model collection configuration
With a ModelCollectionConfiguration
an automatic removal of Model
s
after a defined time span can be configured.
The ModelCollectionConfiguration
is configured for a collection name, a Date
property of the Model
, a time to live time span in seconds.
The configured ModelCollectionConfiguration
adds an index to a specified Date field of a collection with the time to live
interval and removes the models automatically, when the time span has expired.
If a sparse option is required for the collection property, a separate ModelIndex has to be configured. On index creation the index configuration will be merged resulting in one sparse TTL index for that field.
To create a ModelCollectionConfiguration
for the collection myobjects,
the date property creationDate and the time to live period of 180 days, define a
ModelCollectionConfiguration
like this:
@Named public class MyObjectsModelCollectionConfigurations implements ModelCollectionConfiguration { private static final int EXPIRE_AFTER_SECONDS = 180*24*60*60; //180 days @Inject private ModelCollectionConfigurationBuilder builder; public Collection<CollectionConfiguration> getCollectionConfigurations() { return builder. configureTTL( "myobjects", "creationDate", EXPIRE_AFTER_SECONDS). build(); } }
Example 4.6. Creating a ModelCollectionConfiguration
Note
The creation of a TTL index can be prevented by setting the time to live time span to 0. This will not drop an existing index.
Note
A TTL index cannot be created, if a single field index already exists for that field. To create the TTL index, the existing index must be dropped first.
Search indexing
For the full text retrieval and suggestions for Model
s the
SearchService
is used.
To create a SearchIndex
with the name myindex for models of the collection
mycollection, the reindex property creationDate
and their title and text property, define a
SearchIndexConfiguration
like this:
@Named public class MyObjectsSearchIndexes implements SearchIndexConfiguration { @Inject private SearchIndexConfigurationBuilder builder; public Collection<SearchIndex> getSearchIndexes() { return builder. configure("myindex", "mycollection", "creationDate", null, "title", "text"). build(); } }
Example 4.7. Create a SearchIndexConfiguration
You can define SearchIndexCustomizer
s to customize how a Model
will
actually be indexed, for example, if you need to index references to other models or lists. An example
SearchIndexCustomizer
that adds an author's name and email to the comment search index
looks like this:
@Named @Order(value=100) public class CommentAuthorSearchIndexCustomizer implements SearchIndexCustomizer { @Inject private CommentService commentService; public void customize(String indexName, Model model, Map<String, Object> serializedObject) { if ("comments".equals(model.getCollection())) { Comment comment = commentService.createFrom(model); if (comment != null) { CommunityUser user = comment.getAuthor(); if (!user.isAnonymous()) { serializedObject.put("authorName", user.getName() + " " + user.getEmail()); } } } }
You can use the Spring Framework @Order
annotation or the Ordered
interface to define a priority for a customizer. A higher priority means that you can overwrite values defined by
customizers with a lower or no priority. The SearchIndexCustomizer
s defined in the
product have no priority defined, so they can easily be overwritten.
Note
When you work with SearchIndexCustomizer
s to add information about referenced models,
changes to the referenced models will only be indexed when the referring model itself is changed or the whole
index is rebuilt.
Note
The indexing of models as described above is implemented via the TaskQueueService
. To
enable it, set taskqueues.worker-node
to true as described in the Configuration properties and
configure the location of the Apache Solr server with elastic.solr.url
(or
elastic.solr.cloud=true
and elastic.solr.zookeeper.addresses
for SolrCloud).
Caching
Differing from the CoreMedia CMS Content Server and its Unified API the latencies and throughput of the MongoDB are more similar to memcached. This means, caching should only be introduced if performance tests show up bottlenecks.
To avoid bottlenecks, minimize the amount of requests to the MongoDB by minimizing the amount of calls to the
Elastic Core and Elastic Social API. Do not refetch Model
s but keep them during one
request.
Referential Integrity
The ModelService
does not ensure referential integrity between
Model
s or from Models to content beans. When accessing model properties of these types, the
implementation will return proxy objects regardless of whether the targeted Model or ContentBean
exists.
When trying to access the proxy objects, the references will be resolved and in case that the referenced object
does not exist, an UnresolvableReferenceException
will be thrown. The application developer needs to deal with
this case by surrounding access to referenced objects by try/catch blocks (or #attempt blocks in FTLs). Examples are
given below.
for (Comment comment : commentService.getNextUnapprovedComments(true, 10)) { try { if (!comment.getAuthor().isActivated()) { ... } } catch (UnresolvableReferenceException e) { LOG.warn("...", e); } } <#if comments?has_content> <#list comments as comment> <#attempt> ... <div class="comment-author"> ${comment.author.name} </div> ... <#recover> <#-- ignore --> </#attempt> </#if>
Example 4.8. Example try catch