首页 > 解决方案 > 如何从 Hibernate Search 中获取最低和最高价格

问题描述

我想为大多数电子商务网站的产品添加过滤功能。我应该如何根据所选类别获得最低和最高价格?

我已经使用带有 Spring Boot 数据 JPA 的休眠搜索实现了产品过滤器搜索......我正在使用布尔查询构建器根据用户从过滤器中实际选择的内容创建动态查询......举个例子......假设我正在选择男士服装类别和我也得到了属于带有左侧过滤器的服装类别的产品的结果。假设在该类别中,我只允许选择价格范围滑块 100 到 100,这意味着最低产品价格为 100,最高价格为 1000 ......之后我正在过滤使用左侧过滤器(如尺寸和品牌等)的产品数据。如果我选​​择了一个品牌,那么数据会再次刷新为新的价格值,即仅具有品牌类别的服装产品的最小值和最大值。我应该如何在休眠搜索中执行?

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);
query.getResultList();

以上是我选择所有类别产品的示例代码..在此我应该如何创建查询以从所选类别中获取最低和最高价格并添加额外的过滤器将再次更改我的旧价格值..请给我建议..我想要与大多数电子商务网站一样的功能来过滤产品,或者还有其他方法可以做到这一点???..提前谢谢..

标签: javahibernatehibernate-search

解决方案


Hibernate Search 中没有允许您获取最小值和最大值的功能(这需要聚合),但幸运的是,有一个功能应该完全符合您的需要:faceting

简而言之,这允许您在查询之前定义多个价格范围,例如[$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然后将包含您搜索的每个相关方面。


推荐阅读