Я пытаюсь разработать собственный портлет поиска веб-контента для Liferay 7.3.5 GA6, используя SearchContext, IndexSearcherHelperUtil и все остальное.

У меня есть структура DDMS с разными полями, и из того, что я видел в индексе elasticsearch, эти поля индексируются во вложенном документе, например:

"ddmFieldArray": [
{
"ddmFieldName": "ddm__text__37702__nome_it_IT",
"ddmValueFieldName": "ddmFieldValueText_it_IT",
"ddmFieldValueText_it_IT": "Nome esempio",
"ddmFieldValueText_it_IT_String_sortable": "nome esempio"
}
,
{
"ddmFieldName": "ddm__text__37702__descrizione_breve_it_IT",
"ddmValueFieldName": "ddmFieldValueText_it_IT",
"ddmFieldValueText_it_IT": "Esempio di descrizione breve da indicizzare",
"ddmFieldValueText_it_IT_String_sortable": "esempio di descrizione breve da indicizzare"
}
]

Который отличается от старого способа, который я знал, где пользовательские поля были проиндексированы, например ddm__[keyword/text]__[structure_id]__[field_name]

Теперь я понимаю, что этот другой способ индексации связан с улучшением, позволяющим избежать проблем с эластичностью (превышен предел общего количества полей), но ... После выполнения поиска в < em> com.liferay.portal.kernel.search.Document .getFields , поэтому я не могу получить значения полей ddmstructure из индекса эластичного поиска.

Вот код:

long journalArticleClassId = ClassNameLocalServiceUtil.getClassNameId(JournalArticle.class.getName());

SearchContext searchContext = new SearchContext();
searchContext.setClassTypeIds(new long[] {journalArticleClassId});
searchContext.setCompanyId(companyId);
searchContext.setStart(QueryUtil.ALL_POS);
searchContext.setEnd(QueryUtil.ALL_POS);
        
BooleanQuery query = new BooleanQueryImpl();
            
        
MatchQuery approvedQuery = new MatchQuery(Field.STATUS, String.valueOf(WorkflowConstants.STATUS_APPROVED));

query.add(approvedQuery, BooleanClauseOccur.MUST.getName());


Hits resultHits = IndexSearcherHelperUtil.search(searchContext, query);

for (Document doc: resultHits.getDocs()) {          
    doc.getFields().forEach((k, v) -> _log.debug(k)); //No ddm structure field
}

Это все еще улучшение или просто неожиданное поведение?

Есть ли способ решить или расширить это?

Благодарность

0
dgiaig 28 Окт 2020 в 20:39

1 ответ

Лучший ответ

Поле «ddmFieldArray» - это вложенное поле, которое по умолчанию не возвращается. Вы должны получить его из поля источника документа, которое хранится во внутреннем поле «_source» в Elasticsearch (см. https://www.elastic.co/guide/en/elasticsearch/reference/7.9/search-fields.html )

Чтобы сделать это в Liferay, вы должны использовать некоторые методы поиска, которые недоступны в старых классах поиска portal-kernel , вы должны использовать новые классы поиска, которые доступны в < strong> portal-search-api , который находится в modules / apps / portal-search .

Вот те изменения, которые вы должны применить к своему коду:

  • Перед выполнением поиска вы должны добавить флаг "fetchSource" к вашему поиску, добавив этот код:
    searchRequestBuilderFactory.builder(
        searchContext
    ).fetchSource(
        true
    ).build();
  • После выполнения поиска вы должны получить объекты Document из объекта SearchResponse. Этот SearchResponse доступен в searchContext с помощью этого кода:
    /* Execute search */
    IndexSearcherHelperUtil.search(searchContext, query);
    
    /* Get results from search response */
    SearchResponse searchResponse = searchContext.getAttribute("search.response");
    List<SearchHit> resultHits = searchResponse.getSearchHits().getSearchHits();
    
    /* Iterate */
    for (SearchHit searchHit : resultHits)  {
        Document doc = searchHit.getDocument();
    
        ...your stuff...
    }

У вас есть несколько примеров получения исходного кода и получения SearchResponse в следующих классах Liferay:

Я также реализовал отличный пример сценария, который вы можете запустить из: Панель управления => Администрирование сервера => Сценарий .

import com.liferay.registry.*;
import com.liferay.portal.kernel.search.*;
import com.liferay.portal.kernel.search.generic.*;
import com.liferay.portal.search.legacy.searcher.SearchRequestBuilderFactory;
import com.liferay.portal.search.searcher.SearchResponse;
import com.liferay.portal.search.hits.SearchHit;
import com.liferay.portal.search.document.Document;

/* Get SearchRequestBuilderFactory reference using RegistryUtil, because we cannot use "@Reference" in a groovy script */
Registry registry = RegistryUtil.getRegistry();
SearchRequestBuilderFactory searchRequestBuilderFactory = registry.getService(registry.getServiceReference(SearchRequestBuilderFactory.class.getName()));

/* Create SearchContext */
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(com.liferay.portal.kernel.util.PortalUtil.getCompany(actionRequest).getCompanyId());
searchContext.setStart(-1);
searchContext.setEnd(-1);

/* Line to fetch stored source of documents */
searchRequestBuilderFactory.builder(
    searchContext
).fetchSource(
    true
).build();

/* Get journal articles that are approved (status = 0) */
MatchQuery approvedQuery = new MatchQuery(Field.STATUS, String.valueOf(0));
MatchQuery journalArticleQuery = new MatchQuery("entryClassName", com.liferay.journal.model.JournalArticle.class.getName());

BooleanQuery query = new BooleanQueryImpl();
query.add(approvedQuery, BooleanClauseOccur.MUST.getName());
query.add(journalArticleQuery, BooleanClauseOccur.MUST.getName());

/* Execute search */
IndexSearcherHelperUtil.search(searchContext, query);

/* Get results from search response */
SearchResponse searchResponse = searchContext.getAttribute("search.response");
List<SearchHit> resultHits = searchResponse.getSearchHits().getSearchHits();

/* Iterate */
for (SearchHit searchHit : resultHits)  {
    Document doc = searchHit.getDocument();
    out.println("entryClassPK: " + doc.getValue("entryClassPK"));
    out.println("ddmFieldArray: " + doc.getValue("ddmFieldArray"));
    out.println("");
}

В своем коде вы должны заменить использование RegistryUtil аннотацией «@Reference».

Сообщите мне, если у вас возникнут проблемы с моим примером.

4
jorgediaz-lr 30 Окт 2020 в 09:14