56

Spring Boot集成ElasticSearch实现简单的增删查改接口 荐

 5 years ago
source link: http://blog.51cto.com/zero01/2134718?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

SpringBoot集成ElasticSearch

pom.xml文件中,依赖的各jar包版本如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <elasticsearch.version>5.5.2</elasticsearch.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>${elasticsearch.version}</version>
    </dependency>
</dependencies>

在工程中新建一个config包,在该包中创建一个ESConfig配置类,用于构造es的客户端实例对象。代码如下:

package org.zero01.elasticsearch.demo.config;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @program: es-demo
 * @description: es配置类
 * @author: 01
 * @create: 2018-06-28 22:32
 **/
@Configuration
public class ESConfig {

    @Bean
    public TransportClient client() throws UnknownHostException {
        // 9300是es的tcp服务端口
        InetSocketTransportAddress node = new InetSocketTransportAddress(
                InetAddress.getByName("192.168.190.129"),
                9300);

        // 设置es节点的配置信息
        Settings settings = Settings.builder()
                .put("cluster.name", "es")
                .build();

        // 实例化es的客户端对象
        TransportClient client = new PreBuiltTransportClient(settings);
        client.addTransportAddress(node);

        return client;
    }
}

查询接口开发

我现在有一个结构化的索引如下:

mU3YbyM.png!web

该索引中有一些文档数据,如下:

Nb2uaim.png!web

在工程中新建一个controller包,在该包中新建一个 BookCrudController 类,用于演示es增删查改接口demo。我们首先来开发查询接口,代码如下:

package org.zero01.elasticsearch.demo.controller;

import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @program: es-demo
 * @description: es增删查改接口demo
 * @author: 01
 * @create: 2018-07-01 10:42
 **/
@RestController
@RequestMapping("/es/demo")
public class BookCrudController {

    @Autowired
    private TransportClient client;

    /**
     * 按id查询
     * @param id
     * @return
     */
    @GetMapping("/get/book/novel")
    public ResponseEntity searchById(@RequestParam("id") String id) {
        if (id.isEmpty()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

        // 通过索引、类型、id向es进行查询数据
        GetResponse response = client.prepareGet("book", "novel", id).get();

        if (!response.isExists()) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

        // 返回查询到的数据
        return new ResponseEntity(response.getSource(), HttpStatus.OK);
    }
}

启动SpringBoot工程,使用postman进行测试,查询结果如下:

VzqMNjY.png!web

新增接口开发

在 BookCrudController 类中开发新增接口,代码如下:

/**
 * 添加书籍数据
 *
 * @param title       书籍标题
 * @param author      书籍作者
 * @param wordCount   书籍字数
 * @param publishDate 发行时间
 * @return
 */
@PostMapping("/add/book/novel")
public ResponseEntity add(@RequestParam("title") String title,
                          @RequestParam("author") String author,
                          @RequestParam("word_count") int wordCount,
                          @RequestParam("publish_date")
                          @DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
                                  Date publishDate) {
    try {
        // 将参数build成一个json对象
        XContentBuilder content = XContentFactory.jsonBuilder()
                .startObject()
                .field("title", title)
                .field("author", author)
                .field("word_count", wordCount)
                .field("publish_date", publishDate.getTime())
                .endObject();

        IndexResponse response = client.prepareIndex("book", "novel")
                .setSource(content)
                .get();

        return new ResponseEntity(response.getId(), HttpStatus.OK);
    } catch (IOException e) {
        e.printStackTrace();
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

重启SpringBoot工程,使用postman进行测试,测试结果如下:

AjEbQnM.png!web

使用返回的id去查询我们刚刚添加的书籍数据,结果如下:

Jjeiua6.png!web

删除接口开发

代码如下:

/**
 * 按id删除数据
 *
 * @param id
 * @return
 */
@DeleteMapping("/delete/book/novel")
public ResponseEntity delete(@RequestParam("id") String id) {
    DeleteResponse response = client.prepareDelete("book", "novel", id).get();

    return new ResponseEntity(response.getResult(), HttpStatus.OK);
}

重启SpringBoot工程,使用postman进行测试,删除数据成功:

fEruEre.png!web

更新接口开发

代码如下:

/**
 * 根据文档id更新某个文档的数据
 *
 * @param id
 * @param title
 * @param author
 * @param wordCount
 * @param publishDate
 * @return
 */
@PutMapping("/update/book/novel")
public ResponseEntity update(@RequestParam("id") String id,
                             @RequestParam(value = "title", required = false) String title,
                             @RequestParam(value = "author", required = false) String author,
                             @RequestParam(value = "word_count", required = false) Integer wordCount,
                             @RequestParam(value = "publish_date", required = false)
                             @DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
                                     Date publishDate) {
    UpdateRequest update = new UpdateRequest("book", "novel", id);
    try {
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject();

        if (title != null) {
            builder.field("title", title);
        }
        if (author != null) {
            builder.field("author", author);
        }
        if (wordCount != null) {
            builder.field("word_count", wordCount);
        }
        if (publishDate != null) {
            builder.field("publish_date", publishDate.getTime());
        }

        builder.endObject();
        update.doc(builder);

        UpdateResponse response = client.update(update).get();

        return new ResponseEntity(response.getResult().toString(), HttpStatus.OK);
    } catch (Exception e) {
        e.printStackTrace();
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

例如我们要修改文档id为AWQ-N_XeWWbfsfQzkrTh的书籍数据:

maqemaJ.png!web

修改书籍的标题和作者:

NRNv6nR.png!web

修改成功:

qQriEbm.png!web

复合查询接口开发

代码如下:

/**
 * 复合查询接口
 *
 * @param title
 * @param author
 * @param wordCount
 * @param publishDate
 * @param gtWordCount
 * @param ltWordCount
 * @return
 */
@PostMapping("/query/book/novel")
public ResponseEntity query(@RequestParam(value = "title", required = false) String title,
                            @RequestParam(value = "author", required = false) String author,
                            @RequestParam(value = "word_count", required = false) Integer wordCount,
                            @RequestParam(value = "publish_date", required = false)
                            @DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
                                    Date publishDate,
                            @RequestParam(value = "gt_word_count", defaultValue = "0") Integer gtWordCount,
                            @RequestParam(value = "lt_word_count", required = false) Integer ltWordCount) {

    // 组装查询条件
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    if (title != null) {
        boolQuery.must(QueryBuilders.matchQuery("title", title));
    }
    if (author != null) {
        boolQuery.must(QueryBuilders.matchQuery("author", author));
    }
    if (wordCount != null) {
        boolQuery.must(QueryBuilders.matchQuery("word_count", wordCount));
    }
    if (publishDate != null) {
        boolQuery.must(QueryBuilders.matchQuery("publish_date", publishDate));
    }
    // 以word_count作为条件范围
    RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("word_count").from(gtWordCount);
    if (ltWordCount != null && ltWordCount > 0) {
        rangeQuery.to(ltWordCount);
    }
    boolQuery.filter(rangeQuery);

    // 组装查询请求
    SearchRequestBuilder requestBuilder = client.prepareSearch("book")
            .setTypes("novel")
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setQuery(boolQuery)
            .setFrom(0)
            .setSize(10);

    // 发送查询请求
    SearchResponse response = requestBuilder.get();

    // 组装查询到的数据集
    List<Map<String, Object>> result = new ArrayList<>();
    for (SearchHit searchHitFields : response.getHits()) {
        result.add(searchHitFields.getSource());
    }

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

重启SpringBoot工程,使用postman进行测试,测试结果如下:

UJNne2f.png!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK