Model entities are searchable when their data fields are indexed by the search engine. Search and indexing code relies on Search APIs and SPIs.
The extension points (i.e., the interfaces to implement) in this section are
provided by the com.liferay.portal.search.spi
bundle. Calls are also made to
the com.liferay.portal.search.api
bundle’s methods.
Here are the Gradle dependencies for Liferay DXP 7.2.0 GA1:
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.portal.search.spi", version: "3.2.1"
compileOnly group: "com.liferay", name: "com.liferay.portal.search.api", version: "3.7.0"
}
Contributing Model Entity Fields to the Index
Write a ModelDocumentContributor
class to control how model entity fields are
indexed in search engine documents.
Extension Point (SPI): com.liferay.portal.search.spi.model.index.contributor.ModelDocumentContributor<T>
Declare the Component’s indexer.class.name
and its service type as a
ModelDocumentContributor
class:
@Component(
immediate = true,
property = "indexer.class.name=com.liferay.foo.model.FooEntry",
service = ModelDocumentContributor.class
)
public class FooEntryModelDocumentContributor
implements ModelDocumentContributor<FooEntry> {
Implement the contribute
method, calling the
com.liferay.portal.kernel.Document.add()
method appropriate for the data type
the index should use (e.g., addText
for fields that should be searched using a
full text search strategy).
@Override
public void contribute(Document document, FooEntry fooEntry) {
document.addDate(Field.DISPLAY_DATE, fooEntry.getDisplayDate());
document.addDate(Field.MODIFIED_DATE, fooEntry.getModifiedDate());
document.addText(Field.SUBTITLE, fooEntry.getSubtitle());
For fields that should be localized, index a field for each locale in the Site. Many times you’ll want to localize the title and content fields, for example:
for (Locale locale :
LanguageUtil.getAvailableLocales(fooEntry.getGroupId())) {
String languageId = LocaleUtil.toLanguageId(locale);
document.addText(
LocalizationUtil.getLocalizedName(Field.CONTENT, languageId),
content);
document.addText(
LocalizationUtil.getLocalizedName(Field.TITLE, languageId),
fooEntry.getTitle());
}
The above strategy is a good one: loop through the available locales in the
site, then use com.liferay.portal.kernel.util.LocalizationUtil
to add the
localized field name to the document.
The contribute
method is called each time the add
and update
methods in
the entity’s service layer are called.
Configure Re-Indexing and Batch Indexing Behavior
ModelIndexerWriterContributor
classes configure the re-indexing and batch
re-indexing behavior for the model entity. This class’s customize
method is
called when a re-index is triggered from the Search administrative application
found in Control Panel → Configuration → Search, or when a CRUD
operation is made on the entity, if the modelIndexed
method is implemented
in the contributor.
Extension Point (SPI): com.liferay.portal.search.spi.model.index.contributor.ModelIndexerWriterContributor
The bulk of the work is in the customize
method. This code uses the
actionable dynamic query helper method to retrieve all existing Foo entities in
the virtual instance (identified by the Company ID). If you’re using Service
Builder, this query method was generated for you when you built the services.
Each Foo Entry document is then retrieved and added to a collection.
-
First set up the component and class declarations:
@Component( immediate = true, property = "indexer.class.name=com.liferay.foo.model.FooEntry", service = ModelIndexerWriterContributor.class ) public class FooEntryModelIndexerWriterContributor implements ModelIndexerWriterContributor<FooEntry> {
-
Write the
customize
method:@Override public void customize( BatchIndexingActionable batchIndexingActionable, ModelIndexerWriterDocumentHelper modelIndexerWriterDocumentHelper) { batchIndexingActionable.setAddCriteriaMethod( dynamicQuery -> { Property displayDateProperty = PropertyFactoryUtil.forName( "displayDate"); dynamicQuery.add(displayDateProperty.lt(new Date())); Property statusProperty = PropertyFactoryUtil.forName("status"); Integer[] statuses = { WorkflowConstants.STATUS_APPROVED, WorkflowConstants.STATUS_IN_TRASH }; dynamicQuery.add(statusProperty.in(statuses)); }); batchIndexingActionable.setPerformActionMethod( (FooEntry fooEntry) -> { Document document = modelIndexerWriterDocumentHelper.getDocument(fooEntry); batchIndexingActionable.addDocuments(document); }); }
-
Override
getBatchIndexingActionable
:@Override public BatchIndexingActionable getBatchIndexingActionable() { return _dynamicQueryBatchIndexingActionableFactory. getBatchIndexingActionable( _fooEntryLocalService.getIndexableActionableDynamicQuery()); }
-
Override
getcompanyId
, getting the ID from your entity:@Override public long getCompanyId(FooEntry fooEntry) { return fooEntry.getCompanyId(); }
-
Override
getIndexerWriterMode
:@Override public IndexerWriterMode getIndexerWriterMode(FooEntry fooEntry) { int status = fooEntry.getStatus(); if ((status == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_IN_TRASH) || (status == WorkflowConstants.STATUS_DRAFT)) { return IndexerWriterMode.UPDATE; } return IndexerWriterMode.DELETE; }
com.liferay.portal.search.spi.model.index.contributor.helper.IndexerWriterMode
defines the following index-writing options:IndexerWriterMode.DELETE
: instructs the search framework to delete the given document in the search index without re-creating itIndexerWriterMode.PARTIAL_UPDATE
,IndexerWriterMode.UPDATE
: instructs the search framework to update the given document in the search index.IndexerWriterMode.SKIP
: instructs the search framework to not write anything to the search index.
The default is
IndexerWriterMode.UPDATE
. -
Add the services referenced:
@Reference private FooEntryLocalService _fooEntryLocalService; @Reference private DynamicQueryBatchIndexingActionableFactory _dynamicQueryBatchIndexingActionableFactory;
Contribute Fields to Every Document
DocumentContributor
classes (without any indexer.class.name
component
property or type parameter) contribute certain fields to every index document,
regardless of what base entity is being indexed. For example, the
GroupedModelDocumentContributor
contains logic to contribute GROUP_ID
and SCOPE_GROUP_ID
fields for all
documents with a backing entity that’s also a GroupedModel
.