SpringBoot整合SpringDataElasticSearch 完成地理搜索 附近人搜索 距离搜索

找了很多教程,就是由于各种原因运行不起来,在百度中 遇到了以下文章帮助了我

SpringData Elastic 地理搜索 https://www.jianshu.com/p/7373a194a2a3

 

 

1. 环境配置

1.1 依赖

<!-- Springboot的版本为 2.1.3.RELEASE -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

1.2 配置文件  application.yml 

spring:
  data:
    elasticsearch:
      cluster-name: my-application
      cluster-nodes: 127.0.0.1:9300
      repositories:
        enabled: true

 

 

2. 建立索引

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;

@Data
@Document(indexName = "pojo",type = "person",shards = 1,replicas = 0,refreshInterval = "-1")
public class Employee {

    @Id
    private String id;

    @Field
    private String firstName;

    @Field
    private String lastName;

    @Field
    private Integer age = 0;

    @Field
    private String about;


    @GeoPointField
    private GeoPoint geo;

}

 

3. 建立mapping

ElasticSearch 什么是mapping https://blog.csdn.net/sinat_35930259/article/details/80354732#commentBox

不明白什么意思可以看上面的文章 

PUT pojo
{
  "mappings": {
    "person":{
      "properties":{
        "id":{
          "type":"long"
        },
        "firstName":{
          "type":"text"
        },
        "lastName":{
          "type":"text"
        },
        "age":{
          "type":"short"
        },
        "about":{
          "type":"text"
        },
        "geo":{
          "type":"geo_point"
        }
        
      }
    }
  }  
}

 

4.dao层

import com.sunlin.model.Employee;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;

@Component
public interface EmployeeDao  extends ElasticsearchRepository<Employee,String> {


}

 

4. 测试

4.1 首先导入些数据

@Autowired
    private EmployeeDao employeeDao;

    @Test
    public void testAdd() {
        List<Employee> employees = new ArrayList<>();
        for(int i =0;i<10;i++){
            Employee employee = new Employee();
            employee.setAbout("AliP15");
            employee.setFirstName("sun");
            employee.setLastName("lin");
            employee.setAge(21);
            employee.setId(i+"");
            // 纬度,经度
            GeoPoint geoPoint = new GeoPoint(12.71+(i/10),13.25+(i/10));
            employee.setGeo(geoPoint);
            employees.add(employee);
        }
        employeeDao.saveAll(employees);
    }

 

4.2 开始查询

/**
     * 地理搜索
     * @param latitude 纬度
     * @param longitude 经度
     * @param distance 距离
     * @param pageable 分页
     */
    public Page<Employee> findPage(double latitude, double longitude, String distance, Pageable pageable) {
        // 实现了SearchQuery接口,用于组装QueryBuilder和SortBuilder以及Pageable等
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 分页
        nativeSearchQueryBuilder.withPageable(pageable);

        // 间接实现了QueryBuilder接口
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 以某点为中心,搜索指定范围
        GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("geo");
        distanceQueryBuilder.point(latitude, longitude);
        // 定义查询单位:公里
        distanceQueryBuilder.distance(distance, DistanceUnit.KILOMETERS);
        boolQueryBuilder.filter(distanceQueryBuilder);
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        // 按距离升序
        GeoDistanceSortBuilder distanceSortBuilder =
                new GeoDistanceSortBuilder("geo", latitude, longitude);
        distanceSortBuilder.unit(DistanceUnit.KILOMETERS);
        distanceSortBuilder.order(SortOrder.ASC);
        nativeSearchQueryBuilder.withSort(distanceSortBuilder);

        return employeeDao.search(nativeSearchQueryBuilder.build());
    }


    @Test
    public void test(){
        Page<Employee> page = findPage(11.71, 13.25, "50000000", new PageRequest(0, 50));
        System.out.println("开始搜索");

        page.forEach(emp->{
            // calculate() 可以点进去这个方法 看看 就明白每个字段代表什么意思 不懂的话评论
            double distance = GeoDistance.ARC.calculate(11.71, 13.25, emp.getGeo().getLat(),emp.getGeo().getLon(), DistanceUnit.KILOMETERS);
            System.out.println(emp+"; 距离我 : "+distance+"公里");
        });


    }

 

5.结果