liferay 7.3.5ga6自定义索引搜索和ddmfieldarray

yyhrrdl8  于 2021-06-14  发布在  ElasticSearch
关注(0)|答案(1)|浏览(627)

我正在尝试为liferay7.3.5ga6开发一个定制的web内容搜索portlet,使用searchcontext、indexsearcherheloperutil和所有其他东西。
我有一些不同字段的DDM结构,从我在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] 现在,我明白了 这种不同的索引方式是由于一种避免弹性问题的改进(超过了字段总数的限制),但是…执行搜索后,com.liferay.portal.kernel.search.document.getfields中没有ddmfieldarray,因此我无法从ElasticSearch索引中获取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
}

这仍然是一种进步还是仅仅是一种意想不到的行为?
有什么办法可以解决或扩展这个问题吗?
谢谢

vpfxa7rd

vpfxa7rd1#

“ddmfieldarray”字段是一个嵌套字段,默认情况下不会返回该字段。您必须从存储在elasticsearch内部“\u source”字段中的文档源字段中获取它(请参阅https://www.elastic.co/guide/en/elasticsearch/reference/7.9/search-fields.html )
为了在liferay中做到这一点,您必须使用一些在旧门户内核搜索类中不可用的搜索方法,您必须使用位于modules/apps/portal search中的portal search api模块中可用的新搜索类
以下是必须应用于代码的更改:
在执行搜索之前,必须将“fetchsource”标志添加到搜索中添加以下代码:

searchRequestBuilderFactory.builder(
        searchContext
    ).fetchSource(
        true
    ).build();

执行搜索后,必须从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...
    }

在以下liferay类中有一些关于获取源代码和获取searchresponse的示例:
com.liferay.document.library.search.test.dlsearchfixture,请参阅方法searchonlyonesearchhit,其中fetchsource(true)是设置的,searchresponse对象是从searchcontext获取的
com.liferay.account.internal.retriever.accountorganizationretrieverimpl其中一些搜索是使用searchrequest和searchresponse完成的。
使用searchrequestbuilderfactory的com.liferay.asset.internal.util.assethelprimpl。
我还实现了一个groovy脚本示例,您可以从中执行它:controlpanel=>serveradministration=>script

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("");
}

在代码中,应该用“@reference”注解替换registryutil用法。
如果你对我的例子有任何问题,请告诉我。

相关问题