Hibernate search query to filter data based on multiple fields in a list

Hi,

Given the below entity, need to fetch the course where it should match for given languageStr and localizationType inside localizations using hibernate search. For example I want to filter the courses where “languageStr” = “zh” and “localizationType” =“Orginal”, currently it working as `OR" condition, i am looking for “AND” condition. Any help would be appreciated.

@Entity
@Indexed
public class Course{
    @KeywordField
	@Column(unique = true)
	public String id;
	
	@GenericField
	public boolean isActive;
	
	@OneToMany(cascade = CascadeType.ALL)
    @IndexedEmbedded
    @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
	public Set<Localization> localizations = new HashSet<>();
    
}


@Entity
@Indexed
public class  Localization{


    @KeywordField
    public String languageStr;

    @KeywordField(aggregable = Aggregable.YES)
    public String localizationType="";


}

Sample Localization data

"localizations": [
                    {
                        "languageStr": "zh",
                        "localizationType": "Orginal"
                    },
                    {
                        "languageStr": "es",
                        "localizationType": "Subtitled"
                    },
                    {
                        "languageStr": "de",
                        "localizationType": "Subtitled"
                    },
                    {
                        "languageStr": "en",
                        "localizationType": "Original"
                    },
                    {
                        "languageStr": "fr",
                        "localizationType": "Subtitled"
                    },
                    {
                        "languageStr": "ar",
                        "localizationType": "Subtitled"
                    },
                    {
                        "languageStr": "pt",
                        "localizationType": "Subtitled"
                    },
                    {
                        "languageStr": "ja",
                        "localizationType": "Subtitled"
                    }
                ]

Hey,

Thanks for updating the question; now it’s more clear what you’ve been asking about… you’d want to run a nested predicate: Hibernate Search 7.2.0.Alpha2: Reference Documentation

So in your case make localizations nested:

@Entity
@Indexed
public class Course{
    @KeywordField
	@Column(unique = true)
	public String id;
	
	@GenericField
	public boolean isActive;
	
	@OneToMany(cascade = CascadeType.ALL)
    @IndexedEmbedded(structure = ObjectStructure.NESTED) // make the objects nested
    @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
	public Set<Localization> localizations = new HashSet<>();
}

And the query:

List<Course> hits = searchSession.search( Course.class )
.where( f -> f.bool()
	.must(f.match().field("isActive").matching( true ) )
	.must(
		f.nested( "localizations" )
			.add( f.match().field( "localizations.languageStr" ).matching( "zh" ) )
			.add( f.match().field( "localizations.localizationType" ).matching( "Orginal" ) )
	)
).fetchHits( 20 );

Hi @mbekhta

Thanks for your quick response, We are using hibernate version 5.6.15.final in that i am not getting nested(" ").add() method, Can you suggest some alternative solution.

hmm 5.6.15.final isn’t a Hibernate Search version … that’s an ORM one.
Here is the same example with the Hibernate Search 6.0 Hibernate Search 6.0.11.Final: Reference Documentation

replace the f.nested( "localizations" ) with something like

 f.nested().objectField( "localizations" ) 
                .nest( f.bool()
                        .must(f.match().field( "localizations.languageStr" ).matching( "zh" ))
                        .must(f.match().field( "localizations.localizationType" ).matching( "Orginal" ))
                )

Just pick the documentation for the version of Hibernate Search you have and check the section in the docs here Documentation - Hibernate Search

@mbekhta Working thanks.