Message Boards
Unable to Search filtering by Structure Content Fields
Unable to Search filtering by Structure Content Fields
New Member Posts: 5 Join Date: 11/16/20 Recent PostsHello,
Working on Liferay CE 7.3.5 with Elastic Search embedded for development.
I creared a Web Contert Structure containing a field called ContentType which is indexed as following (snippet from the JSON index of ES)
"companyId":"20097",
"rootEntryClassPK":"38645",
"ddmFieldArray":[
{
"ddmFieldName":"ddm__keyword__38361__ContentType",
"ddmValueFieldName":"ddmFieldValueKeyword",
"ddmFieldValueKeyword":"offer",
"ddmFieldValueKeyword_String_sortable":"offer"
},
{
"ddmFieldName":"ddm__keyword__38361__Position",
"ddmValueFieldName":"ddmFieldValueKeyword",
"ddmFieldValueKeyword":[
"[\"home\"]",
"[\"home\"]"
],
"ddmFieldValueKeyword_String_sortable":"[\"home\"]"
},
I am trying programmatically to Search based on ddm_keywork_38361_ContenType (which is non-localised)
For doing so this is my test code trying to add two Term queries as shown in below snippet
// Prepare Search Request
SearchRequestBuilder searchRequestBuilder = searchRequestBuilderFactory.builder();
searchRequestBuilder.emptySearchEnabled(true);
searchRequestBuilder.entryClassNames("com.liferay.journal.model.JournalArticle");
searchRequestBuilder.withSearchContext(searchContext -> {
searchContext.setCompanyId(contextCompany.getCompanyId());
searchContext.setStart(-1);
searchContext.setEnd(-1);
}).fetchSource(true).build();
TermQuery a = queries.term("ddmFieldArray.ddmFieldName", "ddm__keyword__38361__ContentCode");
TermQuery b = queries.term("ddmFieldArray.ddmFieldValueKeyword", "offer");
BooleanQuery booleanQuery = queries.booleanQuery();
booleanQuery.addFilterQueryClauses(a,b);
/* Execute search */
// Add Query Criteria
SearchRequest searchRequest = searchRequestBuilder.query(booleanQuery).build();
// Perform the Search
SearchResponse searchResponse = searcher.search(searchRequest);
System.out.println(searchResponse.getRequestString());
System.out.println(searchResponse.getResponseString());
// Processing the response
SearchHits searchHits = searchResponse.getSearchHits();
List<SearchHit> searchHitsList = searchHits.getSearchHits();
searchHitsList.forEach(searchHit -> {
float hitScore = searchHit.getScore();
Document doc = searchHit.getDocument();
String uid = doc.getString(Field.UID);
System.out.println(StringBundler.concat("Document ", uid, " had a score of ", hitScore));
System.out.println("entryClassPK: " + doc.getValue("entryClassPK"));
System.out.println("ddmFieldArray: " + doc.getValue("ddmFieldArray"));
System.out.println(doc.getValue("ddmFieldArray").getClass().getName());
Map<String, com.liferay.portal.search.document.Field> fields = doc.getFields();
for (Entry<String, com.liferay.portal.search.document.Field> entry : fields.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
});
I am not able to return any Hit with my query.
How can I Query / Filter by a ddmFieldArray field during the search?
Thanks
RE: Unable to Search filtering by Structure Content Fields (Answer)
New Member Posts: 5 Join Date: 11/16/20 Recent PostsFinally I found I need to use Nested Queries along with a Boolean Query to be able for searching on DDMFields indexed.
RE: RE: Unable to Search filtering by Structure Content Fields
New Member Posts: 2 Join Date: 3/4/21 Recent PostsCould you post the solution?
RE: Unable to Search filtering by Structure Content Fields
Liferay Master Posts: 753 Join Date: 1/9/14 Recent PostsYou can use ddmIndexer. createFieldValueQueryFiltermethod, it will internally use a nested elasticsearch query.
You can also copy the internal code of createFieldValueQueryFilter and addFieldValueRequiredTerm methods, see:
- public createFieldValueQueryFilter : https://github.com/liferay/liferay-portal/blob/29b73b9b896c7d44fb5d1800a402698c303d1cf6/modules/apps/dynamic-data-mapping/dynamic-data-mapping-service/src/main/java/com/liferay/dynamic/data/mapping/internal/util/DDMIndexerImpl.java#L279-L298
- protected createFieldValueQueryFilter : https://github.com/liferay/liferay-portal/blob/29b73b9b896c7d44fb5d1800a402698c303d1cf6/modules/apps/dynamic-data-mapping/dynamic-data-mapping-service/src/main/java/com/liferay/dynamic/data/mapping/internal/util/DDMIndexerImpl.java#L644-L680
- protected addFieldValueRequiredTerm: https://github.com/liferay/liferay-portal/blob/29b73b9b896c7d44fb5d1800a402698c303d1cf6/modules/apps/dynamic-data-mapping/dynamic-data-mapping-service/src/main/java/com/liferay/dynamic/data/mapping/internal/util/DDMIndexerImpl.java#L464-L485
RE: Unable to Search filtering by Structure Content Fields
New Member Post: 1 Join Date: 11/11/21 Recent PostsHi all,
the key is to "wrap" the clauses inside a NestedQuery object where to specify that search is inside "ddmFieldArray".
My example is a bit different, because I'm using IndexSearcherHelperUtil, but it works. In my case I need to filter by ddm structure id (structureQuery), and than by a custom field (not localized) named "active", that is a boolean.
//Initialize searchContext
HttpServletRequest httpRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(request));
SearchContext searchContext = SearchContextFactory.getInstance(httpRequest);
//Base structure query
BooleanQuery structureQuery = new BooleanQueryImpl();
structureQuery.addRequiredTerm(Field.GROUP_ID, groupId);
structureQuery.addRequiredTerm(Field.ENTRY_CLASS_NAME, JournalArticle.class.getName());
structureQuery.addRequiredTerm(Field.CLASS_TYPE_ID, ddmStructureId);
structureQuery.addRequiredTerm("visible", Boolean.TRUE); //only visible contents
structureQuery.addRequiredTerm("latest", Boolean.TRUE); //only last version
//Custom fields query
//filter by custom field active=true
BooleanQuery customFieldsQuery = new BooleanQueryImpl();
customFieldsQuery.addRequiredTerm("ddmFieldArray.ddmFieldName", "ddm__keyword__54035__active");
customFieldsQuery.addRequiredTerm("ddmFieldArray.ddmFieldValueKeyword", "true");
//Wrap clauses inside a NestedQuery "ddmFieldArray"
NestedQuery ddmFieldArrayQuery = new NestedQuery("ddmFieldArray", customFieldsQuery);
//Full Query
BooleanQuery searchQuery = new BooleanQueryImpl();
searchQuery.add(structureQuery, BooleanClauseOccur.MUST);
searchQuery.add(ddmFieldArrayQuery, BooleanClauseOccur.MUST);
//query
Hits hits = IndexSearcherHelperUtil.search(searchContext, searchQuery);