close

Filter

Elastic Social Manual / Version 2101

Table Of Contents

4.3 Indexing

Model indexing

Typically, the access to Models 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 Querys 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

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

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 Models 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

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

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 Models 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 SearchIndexCustomizers 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 SearchIndexCustomizers defined in the product have no priority defined, so they can easily be overwritten.

Note

Note

When you work with SearchIndexCustomizers 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

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 Models but keep them during one request.

Referential Integrity

The ModelService does not ensure referential integrity between Models 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 c:catch tags in JSPs). Examples are given below.

for (Comment comment : commentService.getNextUnapprovedComments(true, 10)) {
  try {
    if (!comment.getAuthor().isActivated()) {
      ...
    }
  } catch (UnresolvableReferenceException e) {
    LOG.warn("...", e);
  }
}

<c:forEach var="comment" items="${comments}">
  <c:catch>
    ...
    <div class="comment-author">
      <c:out value="${comment.author.name}"/>
    </div>
    ...
  </c:catch>
</c:forEach>

         

Example 4.8. Example try catch


Search Results

Table Of Contents
warning

Your Internet Explorer is no longer supported.

Please use Mozilla Firefox, Google Chrome, or Microsoft Edge.