1. 程式人生 > >SpringBoot整合Elasticsearch並實現CRUD操作

SpringBoot整合Elasticsearch並實現CRUD操作

配置準備

在build.gradle檔案中新增如下依賴:

    compile "org.elasticsearch.client:transport:5.5.2"
    compile "org.elasticsearch:elasticsearch:5.5.2"
    //es 5.x的內部使用的 apache log4日誌
    compile "org.apache.logging.log4j:log4j-core:2.7"
    compile "org.apache.logging.log4j:log4j-api:2.7"

這裡spring boot使用的是1.5.4版,前些天spring boot 2正式版已經發布,spring boot 2

新特性中有一條是支援kotlin,spring boot 2基於spring 5,spring 5也支援了koltin,所以spring也開始支援函數語言程式設計。

關於版本相容
這裡寫圖片描述

配置訪問Elasticsearch的客戶端,這裡都使用原生es JavaAPI。

@Configuration
public class ElasticSearchConfig {

    @Bean(name = "client")
    public TransportClient getClient() {

        InetSocketTransportAddress node = null
; try { node = new InetSocketTransportAddress(InetAddress.getByName("192.168.124.128"), 9300); } catch (UnknownHostException e) { e.printStackTrace(); } Settings settings = Settings.builder().put("cluster.name", "my-es").build(); TransportClient client = new
PreBuiltTransportClient(settings); client.addTransportAddress(node); return client; } }

SocketTransport埠可以使用http://ip:9200/_nodes方式檢視,這裡預設使用的是9300埠。

CRUD操作

新建一個控制器ElasticSearchController,使用原生的es JavaAPI。

@RestController
public class ElasticSearchController {

    @Autowired
    TransportClient client;
}

在控制器中新增增刪查改方法

  • 增加操作
@PostMapping("add/book/novel")
    public ResponseEntity add(
            @RequestParam(name = "title") String title, @RequestParam(name = "authro") String author,
            @RequestParam(name = "word_count") int wordCount, 
            @RequestParam(name = "publish_date") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")Date publishDate
            )
    {
        try {
            XContentBuilder content = XContentFactory.jsonBuilder().startObject()
                    .field("title", title)
                    .field("author", author)
                    .field("word_count", wordCount)
                    .field("publish_date", publishDate.getTime())
                    .endObject();

            IndexResponse result = this.client.prepareIndex("book", "novel").setSource(content).get();
            return new ResponseEntity(result.getId(), HttpStatus.OK);

        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }
  • 刪除操作
@DeleteMapping("/delete/book/novel")
    public ResponseEntity delete(@RequestParam(name = "id") String id)
    {
        DeleteResponse result = client.prepareDelete("book", "novel", id).get();
        return new ResponseEntity(result.getResult().toString(), HttpStatus.OK);
    }
  • 查詢操作
@GetMapping("/get/book/novel")
    public ResponseEntity get(@RequestParam(name = "id", defaultValue="") String id)
    {
        if (id.isEmpty())
        {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        GetResponse result = this.client.prepareGet("book", "novel", id).get();
        if (!result.isExists())
        {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity(result.getSource(), HttpStatus.OK);
    }
  • 更新操作
@PutMapping("/put/book/novel")
    public ResponseEntity update(@RequestParam(name = "id") String id, @RequestParam(name = "title", required = false) String title,
        @RequestParam(name = "author", required = false) String author
    )
    {
        try {
            XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
            if (title!= null)
            {
                builder.field("title", title);
            }
            if (author != null)
            {
                builder.field("author", author);
            }
            builder.endObject();
            UpdateRequest updateRequest = new UpdateRequest("book", "novel", id);
            updateRequest.doc(builder);

            UpdateResponse result = client.update(updateRequest).get();

            return new ResponseEntity(result.getResult().toString(), HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
  • 複合查詢
@GetMapping("/query/book/novel")
    public ResponseEntity query(@RequestParam(name = "author", required = false) String author,
                                     @RequestParam(name = "title", required = false) String title,
                                     @RequestParam(name = "gt_word_count", defaultValue = "0") int gtWordCount,
                                     @RequestParam(name = "lt_word_count", required = false) Integer ltWordCount)
    {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (author != null)
        {
            boolQueryBuilder.must(QueryBuilders.matchQuery("author",author));
        }
        if (title != null)
        {
            boolQueryBuilder.must(QueryBuilders.matchQuery("title", title));
        }

        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("word_count").from(gtWordCount);
        if (ltWordCount != null && ltWordCount > 0)
        {
            rangeQueryBuilder.to(ltWordCount);
        }

        boolQueryBuilder.filter(rangeQueryBuilder);

        SearchRequestBuilder searchRequestBuilder = this.client.prepareSearch("book")
                .setTypes("novel")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(boolQueryBuilder)
                .setFrom(0)
                .setSize(10);
        System.out.println(searchRequestBuilder); //除錯用

        SearchResponse response = searchRequestBuilder.get();
        List<Map<String, Object>> result = new ArrayList<>();
        for (SearchHit hit : response.getHits())
        {
            result.add(hit.getSource());
        }

        return  new ResponseEntity(result, HttpStatus.OK);
    }

上面的程式碼組織的複合查詢類似下面的Query DSL:

{
    "query":{
        "bool":{
            "must":[
                {"match":{"author":"張三"}},
                {"match":{"title":"Elasticsearch"}}
            ],
            "filter":[
                {"range":
                    {"word_count":{
                            "gt":"0",
                            "lt":"3000"
                        }
                    }
                }
            ]
        }
    }
}