Message Boards

Unable to Search filtering by Structure Content Fields

Daniel Merchan Garcia, modified 2 Years ago.

Unable to Search filtering by Structure Content Fields

New Member Posts: 5 Join Date: 11/16/20 Recent Posts

Hello,

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

Daniel Merchan Garcia, modified 3 Years ago.

RE: Unable to Search filtering by Structure Content Fields (Answer)

New Member Posts: 5 Join Date: 11/16/20 Recent Posts

Finally I found I need to use Nested Queries along with a Boolean Query to be able for searching on DDMFields indexed.

Alain Barrero, modified 3 Years ago.

RE: RE: Unable to Search filtering by Structure Content Fields

New Member Posts: 2 Join Date: 3/4/21 Recent Posts

Could you post the solution?

Denis Torresan, modified 2 Years ago.

RE: Unable to Search filtering by Structure Content Fields

New Member Post: 1 Join Date: 11/11/21 Recent Posts

Hi 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);