Spring Boot 集成 ElasticSearch 实现模糊搜索

作者:王帅@CodeSheep

 

实验环境

  • ES 版本:5.3.0

  • Spring Boot 版本:1.5.9

首先当然需要安装好 Elastic Search 环境,最好再安装上可视化插件 elasticsearch-head来便于我们直观地查看数据。

当然这部分可以参考本人的帖子: 《centos7 上 elastic search安装填坑记》 https://www.jianshu.com/p/04f4d7b4a1d3

我的ES安装在http://113.209.119.170:9200/ 这个地址(该地址需要配到springboot项目中去)

Spring工程创建

这部分没有特殊要交代的,但有几个注意点一定要当心

  • 注意在新建项目时记得勾选web和NoSQL中的Elasticsearch依赖,来张图说明一下吧:

项目自动生成以后pom.xml中会自动添加 spring-boot-starter-data-elasticsearch的依赖:

1
2
3
4
5
6
7
<dependency>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
 
</dependency>

 

  • 本项目中我们使用开源的基于restful的es java客户端 jest,所以还需要在pom.xml中添加 jest依赖:

    1
    2
    3
    4
    5
    6
    7
    <dependency>
     
    <groupId>io.searchbox</groupId>
     
    <artifactId>jest</artifactId>
     
    </dependency>

     

  • 除此之外还必须添加 jna的依赖:

    1
    2
    3
    4
    5
    6
    7
    <dependency>
     
    <groupId>net.java.dev.jna</groupId>
     
    <artifactId>jna</artifactId>
     
    </dependency>

     

否则启动spring项目的时候会报 JNAnotfound.nativemethods will be disabled.的错误:

    • 项目的配置文件application.yml中需要把es服务器地址配置对

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      server:
       
        port: 6325
       
      spring:
       
          elasticsearch:
       
              jest:
       
                  uris:
       
                  - http://113.209.119.170:9200 # ES服务器的地址!
       
                  read-timeout: 5000               

       


代码组织

我的项目代码组织如下:

各部分代码详解如下,注释都有:

      • Entity.java

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        76
        77
        78
        79
        80
        81
        82
        83
        84
        85
            package com.hansonwang99.springboot_es_demo.entity;
         
            import java.io.Serializable;
         
            import org.springframework.data.elasticsearch.annotations.Document;
         
              
         
            public class Entity implements Serializable{
         
              
         
            private static final long serialVersionUID = -763638353551774166L;
         
              
         
            public static final String INDEX_NAME = "index_entity";
         
              
         
            public static final String TYPE = "tstype";
         
              
         
            private Long id;
         
              
         
            private String name;
         
              
         
            public Entity() {
         
              super();
         
            }
         
              
         
            public Entity(Long id, String name) {
         
              this.id = id;
         
            this.name = name;
         
            }
         
              
         
            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;
         
            }
         
              
         
              
         
        }

         

  • TestService.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.hansonwang99.springboot_es_demo.service;
     
      
     
    import com.hansonwang99.springboot_es_demo.entity.Entity;
     
      
     
    import java.util.List;
     
      
     
    public interface TestService {
     
      
     
    void saveEntity(Entity entity);
     
      
     
    void saveEntity(List<Entity> entityList);
     
      
     
    List<Entity> searchEntity(String searchContent);
     
    }

     

  • TestServiceImpl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    package com.hansonwang99.springboot_es_demo.service.impl;
     
      
     
    import java.io.IOException;
     
    import java.util.List;
     
      
     
    import com.hansonwang99.springboot_es_demo.entity.Entity;
     
    import com.hansonwang99.springboot_es_demo.service.TestService;
     
    import org.elasticsearch.index.query.QueryBuilders;
     
    import org.elasticsearch.search.builder.SearchSourceBuilder;
     
    import org.slf4j.Logger;
     
    import org.slf4j.LoggerFactory;
     
    import org.springframework.beans.factory.annotation.Autowired;
     
    import org.springframework.stereotype.Service;
     
    import io.searchbox.client.JestClient;
     
    import io.searchbox.client.JestResult;
     
    import io.searchbox.core.Bulk;
     
    import io.searchbox.core.Index;
     
    import io.searchbox.core.Search;
     
      
     
    @Service
     
    public class TestServiceImpl implements TestService {
     
      
     
    private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImpl.class);
     
      
     
    @Autowired
     
    private JestClient jestClient;
     
      
     
    @Override
     
    public void saveEntity(Entity entity) {
     
    Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build();
     
    try {
     
    jestClient.execute(index);
     
    LOGGER.info("ES 插入完成");
     
    } catch (IOException e) {
     
    e.printStackTrace();
     
    LOGGER.error(e.getMessage());
     
    }
     
    }
     
      
     
      
     
    /**
     
    * 批量保存内容到ES
     
    */
     
    @Override
     
    public void saveEntity(List<Entity> entityList) {
     
    Bulk.Builder bulk = new Bulk.Builder();
     
    for(Entity entity : entityList) {
     
    Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build();
     
    bulk.addAction(index);
     
    }
     
    try {
     
    jestClient.execute(bulk.build());
     
    LOGGER.info("ES 插入完成");
     
    } catch (IOException e) {
     
    e.printStackTrace();
     
    LOGGER.error(e.getMessage());
     
    }
     
    }
     
      
     
    /**
     
    * 在ES中搜索内容
     
    */
     
    @Override
     
    public List<Entity> searchEntity(String searchContent){
     
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
     
    //searchSourceBuilder.query(QueryBuilders.queryStringQuery(searchContent));
     
    //searchSourceBuilder.field("name");
     
    searchSourceBuilder.query(QueryBuilders.matchQuery("name",searchContent));
     
    Search search = new Search.Builder(searchSourceBuilder.toString())
     
    .addIndex(Entity.INDEX_NAME).addType(Entity.TYPE).build();
     
    try {
     
    JestResult result = jestClient.execute(search);
     
    return result.getSourceAsObjectList(Entity.class);
     
    } catch (IOException e) {
     
    LOGGER.error(e.getMessage());
     
    e.printStackTrace();
     
    }
     
    return null;
     
    }
     
    }

     

  • EntityController.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    package com.hansonwang99.springboot_es_demo.controller;
     
      
     
    import java.util.ArrayList;
     
    import java.util.List;
     
      
     
    import com.hansonwang99.springboot_es_demo.entity.Entity;
     
    import com.hansonwang99.springboot_es_demo.service.TestService;
     
    import org.apache.commons.lang.StringUtils;
     
    import org.springframework.beans.factory.annotation.Autowired;
     
    import org.springframework.web.bind.annotation.RequestMapping;
     
    import org.springframework.web.bind.annotation.RequestMethod;
     
    import org.springframework.web.bind.annotation.RestController;
     
      
     
    @RestController
     
    @RequestMapping("/entityController")
     
    public class EntityController {
     
      
     
      
     
    @Autowired
     
    TestService cityESService;
     
      
     
    @RequestMapping(value="/save", method=RequestMethod.GET)
     
    public String save(long id, String name) {
     
    System.out.println("save 接口");
     
    if(id>0 && StringUtils.isNotEmpty(name)) {
     
    Entity newEntity = new Entity(id,name);
     
    List<Entity> addList = new ArrayList<Entity>();
     
    addList.add(newEntity);
     
    cityESService.saveEntity(addList);
     
    return "OK";
     
    }else {
     
    return "Bad input value";
     
    }
     
    }
     
      
     
    @RequestMapping(value="/search", method=RequestMethod.GET)
     
    public List<Entity> save(String name) {
     
    List<Entity> entityList = null;
     
    if(StringUtils.isNotEmpty(name)) {
     
    entityList = cityESService.searchEntity(name);
     
    }
     
    return entityList;
     
    }
     
    }

     


实际实验

增加几条数据,可以使用postman工具,也可以直接在浏览器中输入,如增加以下5条数据:

  1. http://localhost:6325/entityController/save?id=1&name=南京中山陵

  2. http://localhost:6325/entityController/save?id=2&name=中国南京师范大学

  3. http://localhost:6325/entityController/save?id=3&name=南京夫子庙

  4. http://localhost:6325/entityController/save?id=4&name=杭州也非常不错

  5. http://localhost:6325/entityController/save?id=5&name=中国南边好像没有叫带京字的城市了

数据插入效果如下(使用可视化插件elasticsearch-head观看):

我们来做一下搜索的测试:例如我要搜索关键字“南京” 我们在浏览器中输入:

  1. http://localhost:6325/entityController/search?name=南京

搜索结果如下:

刚才插入的5条记录中包含关键字“南京”的四条记录均被搜索出来了!

当然这里用的是standard分词方式,将每个中文都作为了一个term,凡是包含“南”、“京”关键字的记录都被搜索了出来,只是评分不同而已,当然还有其他的一些分词方式,此时需要其他分词插件的支持,此处暂不涉及,后文中再做探索

posted on   胡子就不刮  阅读(6020)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示