SpringBoot2.xプロジェクトモジュール統合のelasticSearch 6.x(geo使用等)


Elasticsearchインストール:https://blog.csdn.net/u012888052/article/details/79710429
ik分詞のインストール:https://blog.csdn.net/u012888052/article/details/81941912
Springboot統合:https://blog.csdn.net/chen_2890/article/details/83895646(このまとめはしっかりしています)
ここでは主にgeoの使用について説明します.
geo機能を使用してElasticsearchTemplateを使用する必要がある場合は、Mappingを使用して作成してからデータを追加する必要があります.そうしないと、geoタイプエラーが発生します.
Repository基本クエリーを使用するには、次の手順に従います.
依存パッケージ

	4.0.0
	Springboot-elasticsearch
	Springboot-elasticsearch
	0.0.1-SNAPSHOT

	 
	
	
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.2.RELEASE
		
	

	
		
		
		
			org.springframework.boot
			spring-boot-starter-data-elasticsearch
		
		
			org.apache.commons
			commons-lang3
			3.5
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
	
	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	

VehicleDtoエンティティークラス
package com.es.dto;

import java.io.Serializable;
import java.util.List;

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.FieldType;

@Document(indexName = "vehicle", type = "special" , shards = 1, replicas = 0)
public class VehicleDto implements Serializable {

	private static final long serialVersionUID = -5483287283894740770L;
	
	@Id
	private Long id;
	
	@Field(type = FieldType.Text)
	private String carDriver;
	
	@Field(type = FieldType.Text)
	private String carType;
	
	//1:ik_smart:        ;2:ik_max_word:        
	@Field(type = FieldType.Text,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
	private String carName;
	
	@Field(type = FieldType.Text)
	private String status;
	
	@Field(type = FieldType.Text)
	private int price;
	
	//      FieldType.Nested
	@Field(type=FieldType.Nested,includeInParent=true)
	private List addressPointDto;
	
	public VehicleDto() {
		
	}

	public Long getId() {
		return id;
	}

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

	public String getCarDriver() {
		return carDriver;
	}

	public void setCarDriver(String carDriver) {
		this.carDriver = carDriver;
	}

	public String getCarType() {
		return carType;
	}

	public void setCarType(String carType) {
		this.carType = carType;
	}

	public String getCarName() {
		return carName;
	}

	public void setCarName(String carName) {
		this.carName = carName;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public List getAddressPointDto() {
		return addressPointDto;
	}

	public void setAddressPointDto(List addressPointDto) {
		this.addressPointDto = addressPointDto;
	}

	@Override
	public String toString() {
		return "VehicleDto [id=" + id + ", carDriver=" + carDriver + ", carType=" + carType + ", carName=" + carName
				+ ", status=" + status + ", price=" + price + ", addressPointDto=" + addressPointDto + "]";
	}

}

ネストされたエンティティAddressPointDto
package com.es.dto;

import java.io.Serializable;
import java.util.Date;

import org.elasticsearch.common.geo.GeoPoint;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;

import com.fasterxml.jackson.annotation.JsonFormat;


@Document(indexName ="vehiclepoint", type = "specialpoint" , shards = 1, replicas = 0)
public class AddressPointDto implements Serializable {

	private static final long serialVersionUID = -5483287283894740770L;
	
	@Id
	private Long id;
	
//	@Field(type = FieldType.String)//1.5.8 spring-boot    
	//1:ik_smart:        ;2:ik_max_word:        
	@Field(type = FieldType.Text,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")//  ik   
	private String name;
	
	//    @Field  ,              type.Keyword
//	@Field(type = FieldType.Keyword)
	@Field(type = FieldType.Text)
//	@Field(type = FieldType.String)//1.5.8 spring-boot    
	private String type;
	
	@Field( type = FieldType.Date,format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date xjTime;
	
//	@Field(type = FieldType.String,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")//1.5.8 spring-boot    
	@Field(type = FieldType.Text,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
	private String remark;
	
	@GeoPointField
    private GeoPoint address;

	public AddressPointDto() {
	}

	public Long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public GeoPoint getAddress() {
		return address;
	}

	public void setAddress(GeoPoint address) {
		this.address = address;
	}

	public Date getXjTime() {
		return xjTime;
	}

	public void setXjTime(Date xjTime) {
		this.xjTime = xjTime;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	@Override
	public String toString() {
		return "VehiclePointEsDto [id=" + id + ", name=" + name + ", type=" + type + ", xjTime=" + xjTime + ", remark="
				+ remark + ", address=" + address + "]";
	}

}

VehicleRepositoryインタフェース
package com.es.service;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;

import com.es.dto.VehicleDto;


@Component
public interface VehicleRepository extends ElasticsearchRepository{

    /**
     * @return
     */
    List findByCarDriver(String carDriver,Pageable pageable);
    
    /**
     * @param name
     * @return
     */
    List findByAddressPointDtoName(String name,Pageable pageable); 
    
    /**
     * @param id1
     * @param id2
     * @return
     */
    List findByCarDriverAndPrice(String carDriver,int price,Pageable pageable);
    
    /**
     * @return
     */
    List findByCarDriverOrCarType(String carDriver,String carType,Pageable pageable);
    
    /**
     * @param id1
     * @param id2
     * @return
     */
    List findByPriceBetween(int price1, int price2);
}

VehicleServiceインタフェース
package com.es.api;

import java.util.List;

import org.springframework.data.domain.Pageable;

import com.es.dto.VehicleDto;

public interface VehicleService {
	
	public void set(VehicleDto dto);
	
	public void setAll(Iterable ite);
	
	public void del(Long id);
	
	public VehicleDto findById(Long id);
	
	public List findAll();
	
	public List findCarDriver(String carDriver,Pageable pageable);
	
	public List findByAddressPointDtoName(String name,Pageable pageable); 
	
	public List findByCarDriverAndPrice(String carDriver,int price,Pageable pageable);
	
	public List findByCarDriverOrCarType(String carDriver,String carType,Pageable pageable);
	
	public List findByPriceBetween(int price1, int price2);
	
}

VehicleServiceImpl実装クラス
package com.es.service.impl;

import java.util.List;
import java.util.Optional;

import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.es.api.VehicleService;
import com.es.dto.VehicleDto;
import com.es.service.VehicleRepository;

@Service
public class VehicleServiceImpl implements VehicleService{
	
	private @Autowired VehicleRepository vehicleRepository;
	
	@Override
	public void set(VehicleDto dto) {
		vehicleRepository.save(dto);
	}

	@Override
	public void setAll(Iterable ite) {
//		vehicleRepository.save(ite);
		vehicleRepository.saveAll(ite);
	}
	
	@Override
	public void del(Long id) {
		vehicleRepository.deleteById(id);
	}
	

	
	@Override
	public VehicleDto findById(Long id) {
//		VehicleEsDto dto = vehicleRepository.findOne(id);
//		return dto;
		Optional dto = vehicleRepository.findById(id);
		return dto.get();
	}

	@Override
	public List findAll() {
		List list = Lists.newArrayList(vehicleRepository.findAll());
		return list;
	}

	@Override
	public List findCarDriver(String carDriver, Pageable pageable) {
		List list = vehicleRepository.findByCarDriver(carDriver, pageable);
		return list;
	}

	@Override
	public List findByCarDriverAndPrice(String carDriver, int price, Pageable pageable) {
		List list = vehicleRepository.findByCarDriverAndPrice(carDriver, price, pageable);
		return list;
	}

	@Override
	public List findByCarDriverOrCarType(String carDriver, String carType, Pageable pageable) {
		List list = vehicleRepository.findByCarDriverOrCarType(carDriver, carType, pageable);
		return list;
	}

	@Override
	public List findByPriceBetween(int price1, int price2) {
		List list = vehicleRepository.findByPriceBetween(price1, price2);
		return list;
	}

	@Override
	public List findByAddressPointDtoName(String name,Pageable pageable) {
		List list = vehicleRepository.findByAddressPointDtoName(name,pageable);
		return list;
	}

}

ElasticsearchTemplate使用
VehicleTemplateServiceインタフェース
package com.es.api;

import java.util.List;

import com.es.dto.VehicleDto;

public interface VehicleTemplateService {
	
	public void bulkIndex(List personList);
	
	public List queryForList(double lat, double lon);
	
	public List queryDto();
	
}

VehicleTemplateServiceImpl実装クラス
package com.es.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import com.es.api.VehicleTemplateService;
import com.es.dto.VehicleDto;

@Service
public class VehicleTemplateServiceImpl implements VehicleTemplateService{
	
	private @Autowired ElasticsearchTemplate elasticsearchTemplate;

	public void bulkIndex(List vehicleDto) {
		int counter = 0;
        List queries = new ArrayList<>();
        //https://github.com/spring-projects/spring-data-elasticsearch/wiki/Geo-indexing-and-request
        //    Mapping           ,     geo    
        elasticsearchTemplate.createIndex(VehicleDto.class);
        elasticsearchTemplate.putMapping(VehicleDto.class);
        for (VehicleDto vehiclePointEsDto : vehicleDto) {
            IndexQuery indexQuery = new IndexQuery();
            indexQuery.setId(vehiclePointEsDto.getId() + "");
                indexQuery.setObject(vehiclePointEsDto);
                //           IndexQueryBuilder   
                //IndexQuery index = new IndexQueryBuilder().withId(VehiclePointEsDto.getId() + "").withObject(VehicleDto).build();
                queries.add(indexQuery);
                if (counter % 500 == 0) {
                    elasticsearchTemplate.bulkIndex(queries);
                    queries.clear();
                    System.out.println("bulkIndex counter : " + counter);
            }
            counter++;
        }
        if (queries.size() > 0) {
            elasticsearchTemplate.bulkIndex(queries);
            System.out.println("    ");
        }
        System.out.println("bulkIndex completed.");
	}
	
	 /**
    *
    geo_distance:                     
    geo_bounding_box:              
    geo_distance_range:             min max     
    geo_polygon:            。
    sort      
    */
	@Override
	public List queryForList(double lat, double lon) {
		Long nowTime = System.currentTimeMillis();
        //      10000    
        GeoDistanceQueryBuilder builder = QueryBuilders.geoDistanceQuery("addressPointDto.address").point(lat, lon)
                .distance(10000, DistanceUnit.METERS);
       
        GeoDistanceSortBuilder sortBuilder = SortBuilders
//        		.geoDistanceSort("address")
        		.geoDistanceSort("addressPointDto.address",new GeoPoint(lat, lon))//     
        		.point(lat, lon)
                .unit(DistanceUnit.METERS)
                .order(SortOrder.ASC);
        //    50 
//		Pageable pageable = new PageRequest(0, 50);
        //     10000    ,       
//        NativeSearchQueryBuilder builder1 = new NativeSearchQueryBuilder().withFilter(builder).withPageable(pageable).withSort(sortBuilder);
        /**
         *   QueryBuilder
         * termQuery("key", obj)     (       )
         * termsQuery("key", obj1, obj2..)          
         * matchQuery("key", Obj)     (    ), field      ,        
         * multiMatchQuery("text", "field1", "field2"..);        , field      
         * matchAllQuery();               
         * matchPhraseQuery()         “%  57%”  
         */
        //     10000    ,name       57,       
//        QueryBuilder queryBuilder = QueryBuilders.termQuery("name", "  57");
//        NativeSearchQueryBuilder builder1 = new NativeSearchQueryBuilder().withQuery(queryBuilder).withFilter(builder).withPageable(pageable).withSort(sortBuilder);
//        NativeSearchQueryBuilder builder1 = new NativeSearchQueryBuilder().withQuery(QueryBuilders.termQuery("name", "  57")).withFilter(builder).withPageable(pageable).withSort(sortBuilder);
		
        /**
         *     
         * must(QueryBuilders) :   AND
         * mustNot(QueryBuilders): NOT
         * should:                  : OR
         */
        QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("carDriver", "  ")).should(QueryBuilders.matchQuery("addressPointDto.name", "  "));
//        QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("remark", "  "));
//        QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("name", "  57")).mustNot(QueryBuilders.matchQuery("id", "43")).should(QueryBuilders.matchQuery("type", "  36"));
        NativeSearchQueryBuilder builder1 = new NativeSearchQueryBuilder().withQuery(queryBuilder).withFilter(builder).withPageable(PageRequest.of(0,50)).withSort(sortBuilder);
        SearchQuery searchQuery = builder1.build();
 
        //queryForList     ,   queryForPage,  10 
        List VehiclePointEsDtoList = elasticsearchTemplate.queryForList(searchQuery, VehicleDto.class);
 
        System.out.println("  :" + (System.currentTimeMillis() - nowTime));
        return VehiclePointEsDtoList;
	}

	@Override
	public List queryDto() {
		 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withQuery(QueryBuilders.termQuery("carDriver", "  1"));
	     SearchQuery searchQuery = builder.build();
	 
        //queryForList     ,   queryForPage,  10 
        List VehiclePointEsDtoList = elasticsearchTemplate.queryForList(searchQuery, VehicleDto.class);
        return VehiclePointEsDtoList;
	}

}

ElasticsearchTestテストクラス
package com.es;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.junit4.SpringRunner;

import com.es.api.VehicleService;
import com.es.api.VehicleTemplateService;
import com.es.dto.AddressPointDto;
import com.es.dto.VehicleDto;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class elasticsearchTest {
	
	@Autowired
    private VehicleService vehicleService;
	@Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
	@Autowired
    private VehicleTemplateService vehicleTemplateService;
	
	
	@Test
    public void queryGeos(){
		double lat = 39.929986;
        double lon = 116.395645;
        List list = vehicleTemplateService.queryForList(lat, lon);
        System.out.println(list);
	}
	
	@Test
    public void bulkIndex(){
		List list = new ArrayList<>();
    	double lat = 39.929986;
        double lon = 116.395645;
    	List addressPointDto = new ArrayList<>();
        for (int i = 1 ; i < 10; i++) {
            double max = 0.00001;
            double min = 0.000001;
            Random random = new Random();
            double s = random.nextDouble() % (max - min + 1) + max;
            DecimalFormat df = new DecimalFormat("######0.000000");
            // System.out.println(s);
            String lons = df.format(s + lon);
            String lats = df.format(s + lat);
            Double dlon = Double.valueOf(lons);
            Double dlat = Double.valueOf(lats);
 
            AddressPointDto person = new AddressPointDto();
            person.setId(Long.valueOf(i));
            person.setName("  " + i);
            person.setType("  " + i);
            person.setXjTime(new Date());
            if(i%2 == 0) {
            	person.setRemark("    ,    "+i);
            }
            if(i%3 == 0) {
            	person.setRemark("     ,    "+i);
            }else{
            	person.setRemark("     ,    "+i);
            }
            
            person.setAddress(new GeoPoint(dlat,dlon));
            addressPointDto.add(person);
        }
    	for (int j = 0; j < 10; j++) {
    		VehicleDto vehicleDto = new VehicleDto();
    		vehicleDto.setId(Long.valueOf(j));
        	vehicleDto.setCarDriver("  "+j);
        	vehicleDto.setCarName(j+".2 ");
        	vehicleDto.setCarType(j+"");
        	vehicleDto.setPrice(j*1000);
        	vehicleDto.setStatus("1");
        	vehicleDto.setAddressPointDto(addressPointDto);
        	list.add(vehicleDto);
		}
    	
    	System.out.println("list:"+list);
		vehicleTemplateService.bulkIndex(list);
	}
	
	@Test
    public void queryDto(){
//		 Pageable pageable = new PageRequest(0, 5);
//		 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("carDriver", "  1"));
		 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("addressPointDto.name", "  1")).withPageable(PageRequest.of(0,5));
	     SearchQuery searchQuery = builder.build();
	 
        //queryForList     ,   queryForPage,  10 
        List vehicleDto = elasticsearchTemplate.queryForList(searchQuery, VehicleDto.class);
		System.err.println("findAll:"+vehicleDto);
	 }
	
	
	@Test
    public void findByAddressPointDtoName(){
		String name = "  1";
		List list = vehicleService.findByAddressPointDtoName(name,PageRequest.of(0,5));
		System.err.println("findAll:"+list);
	 }
	
	@Test
    public void findByCarDriverAndPrice(){
		String carDriver = "  1";
		int price = 1000;
//		Pageable pageable = new PageRequest(0, 5);
		List list = vehicleService.findByCarDriverAndPrice(carDriver, price, PageRequest.of(0,5));
		System.err.println("findAll:"+list);
	 }
	
	@Test
    public void findAll(){
		 List list = vehicleService.findAll();
		 System.err.println("findAll:"+list);
	 }
	
	@Test
    public void del(){
		Long id = 18L;
		vehicleService.del(id);
	}
	
	/**
     *   Index
     */
    @Test
    public void createIndex(){
    	List list = new ArrayList<>();
    	double lat = 39.929986;
        double lon = 116.395645;
    	List addressPointDto = new ArrayList<>();
        for (int i = 1 ; i < 10; i++) {
            double max = 0.00001;
            double min = 0.000001;
            Random random = new Random();
            double s = random.nextDouble() % (max - min + 1) + max;
            DecimalFormat df = new DecimalFormat("######0.000000");
            // System.out.println(s);
            String lons = df.format(s + lon);
            String lats = df.format(s + lat);
            Double dlon = Double.valueOf(lons);
            Double dlat = Double.valueOf(lats);
 
            AddressPointDto person = new AddressPointDto();
            person.setId(Long.valueOf(i));
            person.setName("  " + i);
            person.setType("  " + i);
            person.setXjTime(new Date());
            if(i%2 == 0) {
            	person.setRemark("    ,    "+i);
            }
            if(i%3 == 0) {
            	person.setRemark("     ,    "+i);
            }else{
            	person.setRemark("     ,    "+i);
            }
            
            person.setAddress(new GeoPoint(dlat,dlon));
            addressPointDto.add(person);
        }
    	for (int j = 30; j < 40; j++) {
    		VehicleDto vehicleDto = new VehicleDto();
    		vehicleDto.setId(Long.valueOf(j));
        	vehicleDto.setCarDriver("  "+j);
        	vehicleDto.setCarName(j+".2 ");
        	vehicleDto.setCarType(j+"");
        	vehicleDto.setPrice(j*1000);
        	vehicleDto.setStatus("1");
        	vehicleDto.setAddressPointDto(addressPointDto);
        	list.add(vehicleDto);
		}
    	
//    	vehicleService.set(vehicleDto);
    	System.out.println("list:"+list);
    	//       geo   ElasticsearchTemplate     
    	vehicleService.setAll(list);
    }
}

githubアドレス:https://github.com/LX1309244704/SpringBoot-master/tree/master/springboot-es