[JIRA] (HSEARCH-3325) Search 6 groundwork - Restore support for full-text filters
by Waldemar Kłaczyński (JIRA)
Waldemar Kłaczyński ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *commented* on HSEARCH-3325 ( https://hibernate.atlassian.net/browse/HSEARCH-3325?atlOrigin=eyJpIjoiNWI... )
Re: Search 6 groundwork - Restore support for full-text filters ( https://hibernate.atlassian.net/browse/HSEARCH-3325?atlOrigin=eyJpIjoiNWI... )
It's about simplifying your queries. This allows you to restore the previous strategy of defining filters. Of course, it does not impose anything, it is an additional solution that already existed in the previous version and was very useful. The solution restores the previous functionality. It only consists in the fact that in queries you can, as before, draw on predefined filters. Of course, you can do without it. But it is about building as many tools as possible to simplify work with Apache Lucene. Currently, with my patch, I can write a query in a simpler way:
private class BeansDataModel extends SearchDataModel<Assortment> {
@Override
public SearchQuery<Assortment> search(List<SortMeta> multiSortMeta, Map< String , Object > filters) {
try {
SearchSession session = Search.session(em);
SearchScope<Assortment> scope = session.scope(Assortment.class);
SearchSortFactory sorter = scope.sort();
CompositeSortComponentsStep sort = sorter.composite();
SearchPredicateFactory spf = scope.predicate();
BooleanPredicateClausesStep pricesFilter = spf.bool()
.filter(spf.def( "prices.is-active" ))
.filter(spf.def( "prices.is-shared" )
.param( "user" , identity.getAccount())
);
sort.add(sorter.field( "prices.bruttoPrice_sort" )
.asc()
.mode(MultiValue.MIN)
.filter(pricesFilter));
for (SortMeta sortMeta : multiSortMeta) {
String fieldName = sortMeta.getSortField();
switch (sortMeta.getSortOrder()) {
case ASCENDING:
sort.add(sorter.field(fieldName).asc());
break ;
case DESCENDING:
sort.add(sorter.field(fieldName).desc());
break ;
}
}
PredicateFinalStep select;
if (searchFullText != null ) {
select = scope.predicate().simpleQueryString()
.field( "shoppingName" ).boost(0.5f)
.matching(searchFullText);
} else {
select = scope.predicate()
.matchAll();
}
SearchQuery<Assortment> query = session.search(scope)
.where((f) -> f.bool().must(select)
.filter(f.nested()
.objectField( "prices" )
.nest(pricesFilter)
)).sort(sort.toSort()).toQuery();
return query;
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}
@Entity(name = "Assortment" )
public class Assortment {
....
@IndexedEmbedded(storage = ObjectFieldStorage.NESTED)
@OneToMany(mappedBy = "assortment" , orphanRemoval = true , fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<AssortmentPrice> prices = new ArrayList<>();
...
@FullTextFilter(name = "is-active" , factory = @FilterFactoryRef(type = PricesActiveFilterFactory.class))
@FullTextFilter(name = "is-shared" , factory = @FilterFactoryRef(type = PermissionsFilterFactory.class), params = {
@FilterParam(name = "operation" , value = "share" ),
@FilterParam(name = "field" , value = "sharings" )
})
@Entity(name = "AssortmentPrice" )
public class AssortmentPrice implements Serializable {
....
@FullTextField(analyzer = "permission" )
@Convert(converter = PermissionsConverter.class)
@Column(name = "Sharings" , length = 2048)
private Permissions sharings = new Permissions();
@GenericField
@Column(name = "Active" )
private boolean active = true ;
}
public class PermissionsFilterFactory implements FilterFactory {
@Override
public SearchPredicate create(FilterFactoryContext ctx) {
SearchPredicate filter;
SearchPredicateFactory predicate = ctx.predicate();
Account user = ctx.param( "user" );
String fieldPath = ctx.resolvePath(ctx.param( "field" ));
String operation = ctx.param( "operation" );
if (operation == null ) {
operation = "read" ;
}
PermissionQuery query = new PermissionQuery(fieldPath, operation, user);
filter = predicate.extension(LuceneExtension.get())
.fromLuceneQuery(query)
.toPredicate();
return filter;
}
}
public class PricesActiveFilterFactory implements FilterFactory {
@Override
public SearchPredicate create(FilterFactoryContext ctx) {
SearchPredicate filter;
String fieldPath = ctx.resolvePath( "active" );
filter = ctx.predicate()
.match().field(fieldPath)
.matching( true )
.toPredicate();
return filter;
}
}
Of course I know you can do it differently. Similarly to version 5 it was possible but defining filters in the object type was useful for some. For me it was a valuable property that was in the previous version. I think that this possibility will not hurt in version 6.x, and for some it can be very useful. I have a working solution ready.
( https://hibernate.atlassian.net/browse/HSEARCH-3325#add-comment?atlOrigin... ) Add Comment ( https://hibernate.atlassian.net/browse/HSEARCH-3325#add-comment?atlOrigin... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100122- sha1:53b6171 )