В Hibernate Search нет функции, позволяющей получить минимальное и максимальное значения (что потребует агрегирования), но, к счастью, есть функция, которая должна точно соответствовать тому, что вам нужно: огранка .
Короче говоря, это позволяет перед запросом определить несколько диапазонов цен, например, [$0, $10)
, [$10, $50)
, [$100, $200)
, [$200, $500)
, [$1000, infinite)
. Затем, когда вы получите результаты запроса, вам также будет предоставлено количество подходящих документов для каждого диапазона, что позволит вам предоставить пользователю соответствующие фильтры (и скрыть диапазоны, которые не содержат никакого результата).
Вам нужно добавить что-то подобное вашей сущности:
@Entity
@Indexed
public class Product {
@Field(analyze = Analyze.NO) // You already have something like this, make sure to set analyze = NO
@Facet(forField = "price", encoding = FacetEncodingType.DOUBLE) // You need to add this
private double price;
...
}
Тогда вам следует переиндексировать ваши данные .
Затем напишите ваш запрос так:
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Product.class).get();
Query categoryQuery = queryBuilder.keyword().onFields("subcategory.category.categoryName").matching("Clothing")
.createQuery();
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(categoryQuery, BooleanClause.Occur.MUST);
FullTextQuery query = fullTextEntityManager.createFullTextQuery(builder.build(), Product.class);
// Create the faceting request
FacetingRequest priceFacetingRequest = builder.facet()
.name("priceFaceting")
.onField("price")
.range()
.below(10).excludeLimit()
.from(10).to(20).excludeLimit()
.from(50).to(100).excludeLimit()
.from(100).to(200).excludeLimit()
.from(200).to(500).excludeLimit()
.from(500).to(1000).excludeLimit()
.above(1000)
.createFacetingRequest();
// retrieve facet manager and apply faceting request
FacetManager facetManager = fullTextQuery.getFacetManager();
facetManager.enableFaceting(priceFacetingRequest);
// Retrieve the faceting results
List<Facet> facets = facetManager.getFacets("priceFaceting");
// Process the facets
// The list will contain one element per facet defined above,
// i.e. "(-infinity,10)", "[10,20)", "[50,100)", "[100,200)", "[200,500)", "[500,1000)","[1000,+infinity)"
// Note that by defaults, facets with 0 matching document will be omitted.
for (Facet facet : facets) {
String rangeAsString = facet.getValue();
int matchingDocumentCount = facet.getCount();
// ... do something with the data ...
}
facets
будет содержать каждый соответствующий фасет для вашего поиска.