Package org.hibernate.search.test.spatial

Source Code of org.hibernate.search.test.spatial.SpatialSearchSortByDistanceAndPaging$GeoEntity

/*
* 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.spatial;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient;

import org.apache.lucene.search.Sort;

import org.hibernate.Session;

import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Latitude;
import org.hibernate.search.annotations.Longitude;
import org.hibernate.search.annotations.Spatial;
import org.hibernate.search.annotations.SpatialMode;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.search.query.dsl.Unit;
import org.hibernate.search.spatial.DistanceSortField;
import org.hibernate.search.test.SearchTestBase;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;

/**
* Spatial search with sort by distance and paging orders entities
*
* @author PB
*/
@TestForIssue(jiraKey = "HSEARCH-1267")
public class SpatialSearchSortByDistanceAndPaging extends SearchTestBase {

  private static final int EXPECTED_RESULTS_COUNT = 37;
  private static final double CENTER_LAT = 54.0;
  private static final double CENTER_LON = 18.0;
  private static final double SEARCH_DISTANCE = 20.0;
  private Map<Long, Integer> entitiesIdsSet;
  private int idx;

  @Test
  public void testSortWithoutPaging_isOk() {
    Assert.assertEquals( EXPECTED_RESULTS_COUNT, doSearch( SEARCH_DISTANCE, 50, true ) );
  }

  @Test
  public void testSortWithPageSize5_notOk() {
    Assert.assertEquals(
        "sorting by distance and paging error",
        EXPECTED_RESULTS_COUNT, doSearch( SEARCH_DISTANCE, 5, true )
    );
  }

  @Test
  public void testSortWithPageSize10_notOk() {
    Assert.assertEquals(
        "sorting by distance and paging error",
        EXPECTED_RESULTS_COUNT, doSearch( SEARCH_DISTANCE, 10, true )
    );
  }

  @Test
  public void testNoSortWithPageSize5_isOk() {
    Assert.assertEquals( EXPECTED_RESULTS_COUNT, doSearch( SEARCH_DISTANCE, 5, false ) );
  }

  @Test
  public void testNoSortWithPageSize10_isOk() {
    Assert.assertEquals( EXPECTED_RESULTS_COUNT, doSearch( SEARCH_DISTANCE, 10, false ) );
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();
    prepareTestData();
  }

  /**
   * Search and iterate result pages.
   *
   * @return unique result count
   */
  public int doSearch(double distance, int pageSize, boolean sortByDistance) {
    System.out.println(
        String.format(
            "distance %.2f pageSize %d, sortByDistance %s",
            distance, pageSize, sortByDistance
        )
    );

    entitiesIdsSet = new HashMap<Long, Integer>();
    idx = 0;
    int firstResult = 0;
    List result;

    while ( (result = distanceSearch( CENTER_LAT, CENTER_LON, distance, firstResult, pageSize, sortByDistance ))
        != null && !result.isEmpty() ) {

      printResults( result );

      firstResult += pageSize;
    }
    return entitiesIdsSet.size();
  }

  /**
   * Show result.
   */
  private void printResults(List<GeoEntity> list) {
    for ( GeoEntity entity : list ) {
      System.out.println(
          String.format(
              "%d %f %d%s",
              idx, entity.getDistance(), entity.getId(),
              entitiesIdsSet.containsKey( entity.getId() )
                  ? " was at index " + entitiesIdsSet.get( entity.getId() ) : ""
          )
      );
      if ( !entitiesIdsSet.containsKey( entity.getId() ) ) {
        entitiesIdsSet.put( entity.getId(), idx );
      }
      idx++;
    }
    System.out.println();
  }

  /**
   * Search GeoEntities starting from startLat and startLon within distance
   */
  private List distanceSearch(
      double startLat,
      double startLon,
      double distance,
      int firstResult,
      int maxResult,
      boolean sortByDistance) {

    List resultList = new ArrayList();

    Session sessionHbn = openSession();
    sessionHbn.beginTransaction();

    FullTextSession fTxtSess = Search.getFullTextSession( sessionHbn );

    QueryBuilder builder = fTxtSess.getSearchFactory().buildQueryBuilder().forEntity( GeoEntity.class ).get();

    org.apache.lucene.search.Query luceneQuery = builder.spatial()
        .onDefaultCoordinates()
        .within( distance, Unit.KM )
        .ofLatitude( startLat )
        .andLongitude( startLon )
        .createQuery();

    FullTextQuery hibQuery = fTxtSess.createFullTextQuery( luceneQuery, GeoEntity.class );
    hibQuery.setProjection( FullTextQuery.THIS, FullTextQuery.SPATIAL_DISTANCE );
    hibQuery.setSpatialParameters( startLat, startLon, Spatial.COORDINATES_DEFAULT_FIELD );

    if ( sortByDistance ) {
      Sort distanceSort = new Sort(
          new DistanceSortField(
              startLat,
              startLon,
              Spatial.COORDINATES_DEFAULT_FIELD
          )
      );
      hibQuery.setSort( distanceSort );
    }

    hibQuery.setFirstResult( firstResult ).setMaxResults( maxResult );

    List tmpList = hibQuery.list();

    // copy distance from projection to entities
    for ( Object obj[] : (List<Object[]>) tmpList ) {
      GeoEntity entity = (GeoEntity) obj[0];
      entity.setDistance( (Double) obj[1] );
      resultList.add( entity );
    }

    sessionHbn.getTransaction().commit();
    sessionHbn.close();
    return resultList;
  }

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

  @Entity
  @Indexed
  @Spatial(spatialMode = SpatialMode.RANGE)
  public static class GeoEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @DocumentId
    private Long id;
    @Latitude
    private Double lat;
    @Longitude
    private Double lon;
    @Transient
    private Double distance;
    private String value;

    public GeoEntity() {
    }

    public GeoEntity(Double lat, Double lon, String value) {
      super();
      this.value = value;
      this.lat = lat;
      this.lon = lon;
    }

    public Long getId() {
      return id;
    }

    public void setId(Long id) {
      this.id = id;
    }

    public Double getLat() {
      return lat;
    }

    public void setLat(Double lat) {
      this.lat = lat;
    }

    public Double getLon() {
      return lon;
    }

    public void setLon(Double lon) {
      this.lon = lon;
    }

    public Double getDistance() {
      return distance;
    }

    public void setDistance(Double distance) {
      this.distance = distance;
    }

    public String getValue() {
      return value;
    }

    public void setValue(String value) {
      this.value = value;
    }
  }

  private void prepareTestData() {
    Session sessionHbn = openSession();
    sessionHbn.beginTransaction();

    sessionHbn.saveOrUpdate( new GeoEntity( 54.021861, 18.048349, "v00" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.079361, 18.185003, "v01" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.197314, 18.158194, "v02" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.177621, 18.150250, "v03" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.125537, 18.075425, "v04" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.070479, 18.064328, "v05" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.169191, 18.025334, "v06" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.031556, 18.059142, "v07" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.068104, 18.064764, "v08" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.103417, 18.182243, "v09" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.002537, 18.037648, "v10" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.223375, 18.003011, "v11" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.061524, 18.071648, "v12" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.001563, 18.055457, "v13" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.032163, 18.138202, "v14" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.229162, 18.109120, "v15" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.089290, 18.146594, "v16" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.066932, 18.227589, "v17" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.231832, 18.186478, "v18" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.088117, 18.206227, "v19" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.055539, 18.216111, "v20" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.175193, 18.026838, "v21" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.171762, 18.215527, "v22" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.196967, 18.177212, "v23" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.028481, 18.084819, "v24" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.171071, 18.057752, "v25" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.062881, 18.117777, "v26" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.247034, 18.235728, "v27" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.014431, 18.220235, "v28" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.076813, 18.010077, "v29" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.103647, 18.170640, "v30" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.222894, 18.116137, "v31" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.134499, 18.137614, "v32" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.188910, 18.180216, "v33" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.157758, 18.125557, "v34" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.194089, 18.228482, "v35" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.138517, 18.014723, "v36" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.200781, 18.163288, "v37" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.103558, 18.146598, "v38" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.193829, 18.142770, "v39" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.003273, 18.228929, "v40" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.051599, 18.236313, "v41" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.008487, 18.197262, "v42" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.041120, 18.079304, "v43" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.174614, 18.071497, "v44" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.013968, 18.015511, "v45" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.094368, 18.036610, "v46" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.025288, 18.144333, "v47" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.075499, 18.206458, "v48" ) );
    sessionHbn.saveOrUpdate( new GeoEntity( 54.095646, 18.033243, "v49" ) );

    sessionHbn.getTransaction().commit();
    sessionHbn.close();
    System.out.println( "test data saved" );
  }
}
TOP

Related Classes of org.hibernate.search.test.spatial.SpatialSearchSortByDistanceAndPaging$GeoEntity

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.