Introduction
A Model Document Contributor in Liferay is essential for enhancing the search capabilities by allowing custom data from entities (models) to be indexed and made searchable in Liferay’s search engine (Elasticsearch).
Prerequisites
- Liferay portal 7/7.x
- Elasticsearch
Use of Model Document Contributor in Liferay
- Out of the box, Liferay may not index all the fields of your custom entities. The Model Document Contributor allows you to define and include additional fields from your entities to be indexed, making them searchable.
- By contributing specific data to the search index, you can ensure that relevant fields are available for search queries. This enhances the accuracy and relevance of search results.
- It provides flexibility to control what data is indexed and how it is represented in the search index.
- When you have unique search requirements, such as custom filtering or sorting, the Model Document Contributor allows you to define how your custom model’s data should be indexed and retrieved.
- In summary, the Model Document Contributor plays a vital role in extending and customizing the search functionality in Liferay, ensuring that your data is discoverable and that search results are tailored to your specific needs.
Creating Model Document Contributor in Liferay
For demonstration purposes, I created the web content structure below with three fields: Event Name, Start Date, and End Date.
While creating web content with this structure, these three fields will not be indexed in Liferay’s search document by default. We will create a ModelDocumentContributor for the JournalArticle to index the Start Date in the document.
Please follow the below steps to create a model document contributor.
Step 1 : Create the service portlet.
- Open the Liferay workspace and create a new Liferay Module Project, and select ‘service’ in the Project Template Name.
- Provide the class name and package name and create the module.
Step 2 : Add ModelDocumetContributor to the service.
- Add the below line in the Component property.
indexer.class.name=com.liferay.journal.model.JournalArticle
- Provide service type as ‘ModelDocumentContributor.class’.
- Implement ‘ModelDocumentContributor<JournalArticle>’, and include the unimplemented methods.
Step 3 : Write the code in the contribute method.
package model.contributor;
import com.liferay.journal.model.JournalArticle;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.util.DateUtil;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor;
import java.util.Date;
import java.util.Locale;
import org.osgi.service.component.annotations.Component;
@Component(
immediate = true,
property = {
"indexer.class.name=com.liferay.journal.model.JournalArticle"
},
service = ModelDocumentContributor.class
)
public class JournalArticleModelDocumentContributor implements ModelDocumentContributor {
private static final Log _log = LogFactoryUtil.getLog(JournalArticleModelDocumentContributor.class.getName());
@Override
public void contribute(Document document, JournalArticle journalArticle) {
_log.info("Indexing " + journalArticle.getTitle(journalArticle.getDefaultLanguageId()));
try {
if(journalArticle.getDDMStructure().getStructureKey().equalsIgnoreCase("EVENT")) {
com.liferay.portal.kernel.xml.Document saxDocument = SAXReaderUtil.read(journalArticle.getContent());
String startDateStr = saxDocument.valueOf("//dynamic-element[@name='Date12018025']/dynamic-content/text()");
try {
Date startDate = DateUtil.parseDate("yyyy-MM-dd", startDateStr, new Locale(journalArticle.getDefaultLanguageId()));
document.addDate("startDate", startDate);
document.addDateSortable(Field.getSortableFieldName("startDate"), startDate);
_log.info("Indexed startDate");
} catch (Exception e){
_log.error(e);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Explanation of the code
If the structure key of the JournalArticle is ‘EVENT’, the Start Date field will be fetched from the Journal Article and added to the document. When you deploy this service module, the Start Date field will be also indexed while creating the web content.
Note : we need to execute reindexing for existing content, Once indexed, we can directly use this custom field for searches.
To use this indexed field, I have created a blueprint.
- In the query settings tab, I selected “Web Content Article” as the asset type.
- In the configuration tab, under sort configuration, I have applied sorting by the custom field ‘startDate’ in descending order.
When I use this blueprint on the search results page, the (web contents of the event type structure will be displayed in descending order based on the start date.
Conclusion
Incorporating ModelDocumentContributor in Liferay provides a powerful way to customize how web content structure fields are indexed and searched. By leveraging this feature, you can enhance the search experience by including custom fields, such as dates or other metadata, in your search results. This not only improves the accuracy and relevance of search results but also allows for more flexible sorting and filtering options.