Package org.hibernate.search.test.query.facet

Source Code of org.hibernate.search.test.query.facet.WebShopTest$SearchService

/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.hibernate.search.test.query.facet;

import java.util.List;
import java.util.Map;

import org.apache.lucene.search.Query;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.search.query.facet.Facet;
import org.hibernate.search.query.facet.FacetingRequest;
import org.hibernate.search.query.facet.RangeFacet;
import org.hibernate.search.util.logging.impl.Log;
import org.hibernate.search.util.logging.impl.LoggerFactory;
import org.junit.Test;

import static org.hibernate.search.util.impl.CollectionHelper.newArrayList;
import static org.hibernate.search.util.impl.CollectionHelper.newHashMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
* Simulate a web-shop with basic search which can be refined by facet requests.
*
* @author Hardy Ferentschik
*/
public class WebShopTest extends AbstractFacetTest {

  private static final Log log = LoggerFactory.make( Log.class );

  @Test
  public void testSimulateClient() {
    // get hold of the search service
    SearchService searchService = new SearchService( getSessionFactory() );

    // execute the search and display main query results
    List<Car> cars = searchService.searchCar( "BMW" );
    assertEquals( "We should have matching cars", 12, cars.size() );

    // get the menu items for faceting
    Map<String, List<FacetMenuItem>> facetMenuItems = searchService.getMenuItems();

    List<FacetMenuItem> colorMenuItems = facetMenuItems.get( SearchService.colorFacetName );
    assertEquals( "Wrong number of menu entries", 4, colorMenuItems.size() );
    for ( FacetMenuItem item : colorMenuItems ) {
      assertFalse( item.isSelected() );
    }

    List<FacetMenuItem> ccsMenuItems = facetMenuItems.get( SearchService.cubicCapacityFacetName );
    assertEquals( "Wrong number of menu entries", 3, ccsMenuItems.size() );
    for ( FacetMenuItem item : ccsMenuItems ) {
      assertFalse( item.isSelected() );
    }

    // let the user select a facet menu
    FacetMenuItem selectedItem = facetMenuItems.get( SearchService.colorFacetName ).get( 0 );
    assertEquals( "Wrong facet value", "red", selectedItem.getValue() );
    assertEquals( "Wrong facet count", 3, selectedItem.getCount() );

    cars = searchService.selectMenuItem( selectedItem );
    assertEquals( "We should have matching cars", 3, cars.size() );

    // get the new menu items
    facetMenuItems = searchService.getMenuItems();

    colorMenuItems = facetMenuItems.get( SearchService.colorFacetName );
    assertEquals( "Wrong number of menu entries", 4, colorMenuItems.size() );
    FacetMenuItem menuItem = colorMenuItems.get( 0 );
    assertEquals( "Wrong facet count", 3, menuItem.getCount() );
    assertTrue( menuItem.isSelected() );

    ccsMenuItems = facetMenuItems.get( SearchService.cubicCapacityFacetName );
    assertEquals( "Wrong number of menu entries", 3, ccsMenuItems.size() );
    for ( FacetMenuItem item : ccsMenuItems ) {
      assertFalse( item.isSelected() );
    }

    // deselect the menuitem again
    cars = searchService.deSelectMenuItem( menuItem );
    assertEquals( "We should have matching cars", 12, cars.size() );
  }


  @Override
  public void loadTestData(Session session) {
    Transaction tx = session.beginTransaction();
    List<Car> allCars = newArrayList();
    for ( String make : makes ) {
      for ( String color : colors ) {
        for ( int cc : ccs ) {
          Car car = new Car( make, color, cc );
          session.save( car );
          allCars.add( car );
        }
      }
    }
    log.infof( "Indexed cars: %s", allCars );
    tx.commit();
    session.clear();
  }

  @Override
  protected Class<?>[] getAnnotatedClasses() {
    return new Class[] {
        Car.class,
    };
  }

  public static class SearchService {
    public static final String colorFacetName = "color";
    public static final String cubicCapacityFacetName = "cubicCapacity";
    private SessionFactory factory;
    private FullTextQuery currentFullTextQuery;
    private Map<String, List<FacetMenuItem>> menuItems;
    private String queryString;
    private List<Facet> selectedFacets = newArrayList();

    public SearchService(SessionFactory factory) {
      this.factory = factory;
    }

    /**
     * Service method for a potential car search website
     *
     * @param queryString the query string specified by the user
     *
     * @return a list of cars matching the query
     */
    private List<Car> searchCar(String queryString) {
      this.queryString = queryString;
      FullTextSession fullTextSession = Search.getFullTextSession( factory.openSession() );
      buildFullTextQuery( queryString, fullTextSession );

      Transaction tx = fullTextSession.beginTransaction();
      List<Car> cars = currentFullTextQuery.list();
      tx.commit();

      fullTextSession.close();

      return cars;
    }

    private void buildFullTextQuery(String queryString, FullTextSession fullTextSession) {
      // get a query builder
      final QueryBuilder builder = fullTextSession.getSearchFactory()
          .buildQueryBuilder()
          .forEntity( Car.class )
          .get();

      // build a Lucene query
      final Query query = builder.keyword().onField( "make" ).matching( queryString ).createQuery();

      // create facets for navigation
      // discrete faceting
      final FacetingRequest colorFacet = builder.facet()
          .name( colorFacetName )
          .onField( "color" )
          .discrete()
          .createFacetingRequest();
      // range faceting
      final FacetingRequest priceFacet = builder.facet()
          .name( cubicCapacityFacetName )
          .onField( "cubicCapacity" )
          .range()
          .below( 2500 ).excludeLimit()
          .from( 2500 ).to( 3000 )
          .above( 3000 ).excludeLimit()
          .createFacetingRequest();


      // create the fulltext query, enable the facets via the facet manager and return the results
      currentFullTextQuery = fullTextSession.createFullTextQuery( query, Car.class );
      currentFullTextQuery.setFirstResult( 0 ).setMaxResults( 20 );
      currentFullTextQuery.getFacetManager().enableFaceting( colorFacet ).enableFaceting( priceFacet );
    }

    public Map<String, List<FacetMenuItem>> getMenuItems() {
      menuItems = newHashMap();
      List<FacetMenuItem> items = newArrayList();

      int i = 0;
      for ( Facet facet : currentFullTextQuery.getFacetManager().getFacets( colorFacetName ) ) {
        items.add( new FacetMenuItem( facet, selectedFacets.contains( facet ), i ) );
        i++;
      }
      menuItems.put( colorFacetName, items );

      items = newArrayList();
      i = 0;
      for ( Facet facet : currentFullTextQuery.getFacetManager().getFacets( cubicCapacityFacetName ) ) {
        items.add( new FacetMenuItem( facet, selectedFacets.contains( facet ), i++ ) );
      }
      menuItems.put( cubicCapacityFacetName, items );
      return menuItems;
    }

    public List<Car> selectMenuItem(FacetMenuItem item) {
      // find the right facet using the facet manager
      List<Facet> facets = currentFullTextQuery.getFacetManager().getFacets( item.getFacetingName() );
      Facet facet = facets.get( item.getIndex() );
      selectedFacets.add( facet );

      // rer-run the query
      FullTextSession fullTextSession = Search.getFullTextSession( factory.openSession() );
      buildFullTextQuery( queryString, fullTextSession );

      Transaction tx = fullTextSession.beginTransaction();
      // use the facet to narrow down the query
      currentFullTextQuery.getFacetManager()
          .getFacetGroup( item.getFacetingName() )
          .selectFacets( selectedFacets.toArray( new Facet[] { } ) );
      List<Car> cars = currentFullTextQuery.list();
      tx.commit();
      fullTextSession.close();
      return cars;
    }

    public List<Car> deSelectMenuItem(FacetMenuItem item) {
      // find the right facet using the facet manager
      List<Facet> facets = currentFullTextQuery.getFacetManager().getFacets( item.getFacetingName() );
      Facet facet = facets.get( item.getIndex() );
      selectedFacets.remove( facet );

      // rer-run the query
      FullTextSession fullTextSession = Search.getFullTextSession( factory.openSession() );
      buildFullTextQuery( queryString, fullTextSession );

      Transaction tx = fullTextSession.beginTransaction();
      // use the facet to narrow down the query
      currentFullTextQuery.getFacetManager()
          .getFacetGroup( item.getFacetingName() )
          .selectFacets( selectedFacets.toArray( new Facet[] { } ) );
      List<Car> cars = currentFullTextQuery.list();
      tx.commit();
      fullTextSession.close();
      return cars;
    }

  }

  // simulate some sort of frontend data structure for displaying the facet menu
  static class FacetMenuItem {
    private final boolean isSelected;
    private final int index;
    private final String facetingName;
    private final Facet facet;

    public FacetMenuItem(Facet facet, boolean selected, int index) {
      this.isSelected = selected;
      this.facet = facet;
      this.facetingName = facet.getFacetingName();
      this.index = index;
    }

    public boolean isSelected() {
      return isSelected;
    }

    public int getCount() {
      return facet.getCount();
    }

    public String getValue() {
      String value;
      if ( facet instanceof RangeFacet ) {
        // this could get more involved
        RangeFacet rangeFacet = (RangeFacet) facet;
        value = rangeFacet.getMin().toString() + " - " + rangeFacet.getMax().toString();
      }
      else {
        value = facet.getValue();
      }
      return value;
    }

    public int getIndex() {
      return index;
    }

    public String getFacetingName() {
      return facetingName;
    }

    @Override
    public String toString() {
      final StringBuilder sb = new StringBuilder();
      sb.append( "FacetMenuItem" );
      sb.append( "{isSelected=" ).append( isSelected );
      sb.append( ", facet=" ).append( facet );
      sb.append( '}' );
      return sb.toString();
    }
  }
}
TOP

Related Classes of org.hibernate.search.test.query.facet.WebShopTest$SearchService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.