简体   繁体   中英

Selected facet should not filter own group using hibernate search

If I have some Products with color and size. Jeans Blue Size L Jeans Red Size S T-shirt REd Size S and so on..

Doing a facet search using hibernate-search works as quite well. But if I select one of the criteria, I would expect that the values of the own group are not filtered. for Example

Color Red (2) Blue (3)

Size S (1) M (2) L (3)

If I selected the red color using something like this

fullTextQuery.getFacetManager().getFacetGroup(FACET_COLOR).selectFacets(colorFacet)

This selection should influence the overall Results of the Item List and the Result of the Size Facets. But of course I don't want that the Blue option to vanish. My expected behavior is pretty much how its done on bigger ecommerce sites. But in my example the selected color red also changes the own group.

I'm I missing something? This is my example:

public SearchResponse search(SearchRequest request)
    {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);

        QueryBuilder queryBuilder =
          fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Product.class).get();

        BooleanJunction bool = queryBuilder.bool().must(queryBuilder.all().createQuery());

        FacetingRequest colorFacetRequest = queryBuilder.facet().name(FACET_COLOR).onField(FACET_COLOR)
          .discrete().createFacetingRequest();

        FacetingRequest sizeFacetRequest = queryBuilder.facet().name(FACET_SIZE).onField(FACET_SIZE)
          .discrete().createFacetingRequest();

        FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(bool.createQuery(), Product.class);
        fullTextQuery.getFacetManager().enableFaceting(colorFacetRequest);
        fullTextQuery.getFacetManager().enableFaceting(sizeFacetRequest);

        if (!StringUtils.isEmpty(request.color))
        {
            fullTextQuery.getFacetManager().getFacets(FACET_COLOR)
              .stream().filter(f -> f.getValue().equals(request.color)).forEach(found -> {
                  fullTextQuery.getFacetManager().getFacetGroup(FACET_COLOR).selectFacets(found);
              });
        }

        if (!StringUtils.isEmpty(request.size))
        {
            fullTextQuery.getFacetManager().getFacets(FACET_SIZE)
              .stream().filter(f -> f.getValue().equals(request.size)).forEach(found -> {
                  fullTextQuery.getFacetManager().getFacetGroup(FACET_SIZE).selectFacets(found);

              });
        }

        List<SearchFacet> colorFacet = fullTextQuery.getFacetManager().getFacets(FACET_COLOR)
          .stream().map(f -> new SearchFacet(f.getValue(), f.getCount())).collect(Collectors.toList());
        List<SearchFacet> sizeFacet = fullTextQuery.getFacetManager().getFacets(FACET_SIZE)
          .stream().map(f -> new SearchFacet(f.getValue(), f.getCount())).collect(Collectors.toList());

        return new SearchResponse(sizeFacet, colorFacet, fullTextQuery.getResultList());

    }

disabling each group before the getFacets Methods does not seem very clean

Thanks

Let me start my answer by explaining a key difference to help you with your search.

The first difference is that filters needs to be a string and facetFilters needs to be an array

You can use the second, ie facetFilters array to pass jobs in Paris, London etc . that will collectively trim down your data set


You have to pick one at the top level and then the other would be a nested criteria inside.

For eg you can either do a top level filter or top level facet search and then apply the filters within.

You could achieve this in different ways, for eg he gets the records and then drills down. from @Gunnar answer

Record lastRecord = ...;

QueryBuilder queryBuilder = fullTextSession
    .getSearchFactory()
    .buildQueryBuilder()
    .forEntity(Record.class).get();

Query query = queryBuilder.range()
    .onField( "created" )
    .above( lastRecord.getCreated() )
    .createQuery();

FullTextQuery fullTextQuery = fulllTextSession.createFullTextQuery(
    query, Record.class
);

Now if you want to aggreate those query results only

SearchSession searchSession = Search.session( entityManager );

AggregationKey<Map<Genre, Long>> countsByGenreKey = AggregationKey.of( "countsByGenre" ); 

SearchResult<Book> result = searchSession.search( Book.class ) 
        .where( f -> f.match().field( "title" ) 
                .matching( "robot" ) )
        .aggregation( countsByGenreKey, f -> f.terms() 
                .field( "genre", Genre.class ) )
        .fetch( 20 ); 

Map<Genre, Long> countsByGenre = result.aggregation( countsByGenreKey ); 

The last scenario from your jobs comments is by doing a collection of filters like here

There is already an enhancement request about this: https://hibernate.atlassian.net/browse/HSEARCH-713

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM