当前位置:   article > 正文

Spring Boot整合elasticsearch实现全文检索_elasticsearch java 全文检索

elasticsearch java 全文检索


1.引入

1.1 Luence

Lucene是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

1.2 Solr

Solr是一个基于Luence的企业级全文搜索服务器,它童工了比Luence更加丰富的查询语言,同时实现了可配置、可扩展,同时对索引和搜索性能进行了优化。Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中。

Solr 索引的实现方法是用 POST方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引。Solr 搜索只需要使用提供的Web-service的API接口,来发送 HTTP GET 请求,然后对返回XML、json等格式的查询结果进行解析,组织页面布局。

1.3 ElasticSearch

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene

source: 百度百科


2. ElasticSearch安装

2.1 云服务器安装
2.1.1. docker安装
  • 搜索镜像:如果docker search elasticsearch,或者到docker hub中进行搜索
    在这里插入图片描述

    如果不指定版本可能会无法进行安装,因此,最好指定安装的版本号。

  • 拉取镜像

    docker pull elasticsearch:7.8.0
    
    • 1
  • 运行镜像并进行端口映射

    [root@izbp15ffbqqbe97j9dcf5dz ~]# docker images
    REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
    docker.io/elasticsearch   7.8.0               121454ddad72        6 days ago          810 MB
    [root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -d -p 9200:9200 -p 9300:9300 --name ES01 121454ddad72
    
    • 1
    • 2
    • 3
    • 4

    NOTE:

    • -e ES_JAVA_OPTS="-Xms512m -Xmx512m":只用指定启动elasticsearch所需的内存大小,elasticsearch默认使用内存大小为2G,,如果不够则无法正常启动。因为我的云服务器只有2G的内存,因此,这里最大可用内存和最小可用内存都为512m
    • -e "discovery.type=single-node":单节点安装要加上,否则会报ERROR: [1] bootstrap checks failed
    • -p 9200:9200 -p 9300:9300:进行端口映射,便于远程访问
  • 查看是否正常运行,可以看到正常运行中

    [root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps 
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
    200c0b2c5735        121454ddad72        "/tini -- /usr/loc..."   11 minutes ago      Up 10 minutes       0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp                                               ES01
    afc7a1ab33ce        95bc78c8d15d        "docker-entrypoint..."   5 hours ago         Up 5 hours          4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp   rabbitmq
    25bd2268623c        redis               "docker-entrypoint..."   22 hours ago        Up 22 hours         0.0.0.0:6379->6379/tcp                                                                       redis
    53b9351e2a7f        mysql               "docker-entrypoint..."   29 hours ago        Up 29 hours         0.0.0.0:3306->3306/tcp, 33060/tcp                                                            wizardly_cori
    [root@izbp15ffbqqbe97j9dcf5dz ~]# 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
2.1.2 配置安全规则

登录云服务器,选择左侧的安全组中的配置规则,手动添加访问规则:
在这里插入图片描述

2.1.3 远程访问

使用ip:9200请求访问elasticsearch,如果浏览器输出如下信息,表示设置成功。

{
  "name" : "200c0b2c5735",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "Ef-bRe0lS8Sgg6s7T4y29g",
  "version" : {
    "number" : "7.8.0",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
    "build_date" : "2020-06-14T19:35:50.234439Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
2.2 windows安装
2.2.1 elasticsearch安装

首先到elasticsearch官网下载所需的压缩包
在这里插入图片描述

下载结束后解压即可用。找到bin目录下的elasticsearch.bat,双击即可在后台运行elasticsearch服务。接着在浏览器中输入localhost:9200,如果能看到如下信息,说明elasticsearch正常启动

{
  "name" : "DESKTOP-5UNDPP9",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "BmT8EaJsRZKDAfj34tmJ2A",
  "version" : {
    "number" : "7.6.1",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "aa751e09be0a5072e8570670309b1f12348f023b",
    "build_date" : "2020-02-29T00:15:25.529771Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

NOTE:

  • 安装elasticsearch确保JDK已正确安装

  • elasticsearch启动时默认占用内存大小为1G,如果想降低所占内存可到解压目录下的config/jvm.options修改其中的-Xms-Xmx参数,如:

    -Xms512m
    -Xmx1512m
    
    • 1
    • 2
2.2.2 head插件安装

安装前请确保Nodejs环境已安装~

首先到elasticsearch-head中下载code的压缩包,下载完毕后解压,并到命令行窗口切换到解压目录。运行npm install安装插件,最后使用npm run start命令启动插件。

为了连接前面安装的elasticsearch,还需要解决跨域问题。在elasticsearch的解压目录下找到config/elasticsearch.yml文件,添加如下设置,并使用UTF-8格式保存。不然可能会出现闪退问题:

http.cors.enabled: true
http.cors.allow-origin: "*"
  • 1
  • 2

在浏览器中输入localhost:9100访问会看到如下页面,表示启动成功。
在这里插入图片描述

在Connect左侧的地址栏中输入http://127.0.0.1:9200/便可连接上elasticsearch。

我使用http://localhost:9200/无法连接成功,不知道为什么~

在这里插入图片描述

2.2.3 安装ElasticHD

elasticsearch-head实在是不符合现代审美,所以可以选择安装ElasticHD,它是一个Elasticsearch 可视化DashBoard, 支持Es监控、实时搜索,Index template快捷替换修改,索引列表信息查看, SQL converts to DSL等。

这里同样只介绍通过云服务器的docker安装,首先到docker hub上搜索镜像
在这里插入图片描述
通过docker pull containerize/elastichd命令拉取镜像:

root@izbp15ffbqqbe97j9dcf5dz ~]# docker pull containerize/elastichd
Using default tag: latest
Trying to pull repository docker.io/containerize/elastichd ... 
latest: Pulling from docker.io/containerize/elastichd
43d680a959df: Pull complete 
de979aec8d7a: Pull complete 
1216b09132aa: Pull complete 
Digest: sha256:2b20e180418f3b6d0d37f2be4485244960131a9d6ce1d51ab6afbc6f40685e20
Status: Downloaded newer image for docker.io/containerize/elastichd:latest

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

通过docker ps查看正在运行的elasticsearch服务的名字,我这里是ES01。然后使用docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd命令安装,最后使用docker ps查看是否启动成功。

[root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd
427bdf04b78c49794fc65106074476751d58e939bb43a448785354307e855412
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
427bdf04b78c        containerize/elastichd   "ElasticHD"              4 seconds ago       Up 3 seconds        0.0.0.0:9800->9800/tcp                                                                       clever_heisenberg
5c09fb35ce4f        e2a76963bc18             "/bin/sh -c 'node_..."   4 minutes ago       Up 4 minutes        0.0.0.0:9100->9100/tcp                                                                       ES-Head
200c0b2c5735        121454ddad72             "/tini -- /usr/loc..."   42 hours ago        Up 42 hours         0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp                                               ES01
afc7a1ab33ce        95bc78c8d15d             "docker-entrypoint..."   47 hours ago        Up 47 hours         4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp   rabbitmq
25bd2268623c        redis                    "docker-entrypoint..."   2 days ago          Up 2 days           0.0.0.0:6379->6379/tcp                                                                       redis
53b9351e2a7f        mysql                    "docker-entrypoint..."   2 days ago          Up 2 days           0.0.0.0:3306->3306/tcp, 33060/tcp                                                            wizardly_cori

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

此外,为了实现远程访问,还需要在服务器安全组添加安全规则
在这里插入图片描述
配置结束后在浏览器输入http://ip:9800/,如果访问成功会看到如下dashboard,并且可以在地址栏中输入http://ip:9200/来连接elasticsearch服务。
在这里插入图片描述

2.2.4安装kibana

Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。

首先同样需要elasticsearch官网下载Kibana的压缩包,下载结束后解压即可用。双击运行bin/Kbina.bat即可启动服务,在浏览器中输入localhost:5601可看到如下界面,说明启动成功。
在这里插入图片描述


3. Spring Boot整合ElasticSearch

3.1 环境搭建

Spring Boot整合elastissearch首先需要引入其依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.8.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

由于Spring Boot自动引入的elasticsearch版本太低,因此,还需要更改elasticsearch的版本,使其和本地安装的版本一致:

<elasticsearch.version>7.8.0</elasticsearch.version>
  • 1

elasticsearch针对于Java提供了两个版本的客户端来使用它,分别是低版本的RestClient和高版本的RestHighLevelClient,这里演示使用RestHighLevelClient。

RestClient官方文档

RestHighLevelClient官方文档

最后在Ioc容器中注入RestHighLevelClient,方便后续的使用。

@Configuration
public class ElasticSearchConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client =  new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9200, "http")
                )
        );
        return client;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
3.2 索引操作

添加索引:

@Test
public void testCreateIndex() throws IOException {
    // 创建索引请求
    CreateIndexRequest request = new CreateIndexRequest("test.index");
    // 客户端执行请求IndicesClient,请求获得响应
    CreateIndexResponse createIndexResponse = restHighLevelClient.indices().
        create(request, RequestOptions.DEFAULT);
    System.out.println(createIndexResponse);
    // org.elasticsearch.client.indices.CreateIndexResponse@274eb315
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

执行单元测试,查看elasticsearch发现test.index已经添加成功。
在这里插入图片描述

查询索引是否存在:

@Test
public void testIndexExist() throws IOException {
    GetIndexRequest request = new GetIndexRequest("test.index");
    boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    System.out.println(exists); // true
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

执行单元测试,控制台输出true,表示之前添加的test.index确实存在。

删除索引

@Test
public void testIndexDelete() throws IOException {
    DeleteIndexRequest request = new DeleteIndexRequest("test.index");
    AcknowledgedResponse delete = restHighLevelClient.indices().delete(request,
                                                                       RequestOptions.DEFAULT);
    System.out.println(delete.isAcknowledged());  // true
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

执行单元测试,查看elasticsearch发现test.index已经被删除。
在这里插入图片描述

3.3 文档操作

添加文档

@Test
public void testAddDoc() throws IOException {
    Person person = Person.builder().name("kobe").age(18).build();
    // 创建请求
    IndexRequest request = new IndexRequest("test.index");
    request.id("1");
    request.timeout(TimeValue.timeValueMinutes(1));
    request.timeout("1s");

    // 将数据放入请求
    request.source(JSON.toJSONString(person), XContentType.JSON);

    // 客户端发送请求 , 获取响应的结果
    IndexResponse indexResponse = restHighLevelClient.index(request,
                                                            RequestOptions.DEFAULT);
    System.out.println(indexResponse.toString());
    System.out.println(indexResponse.status());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

​ 执行单元测试,控制台输出:

IndexResponse[index=test.index,type=_doc,id=1,version=2,result=updated,seqNo=1,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
OK
  • 1
  • 2

同时查看elasticsearch,发现确实添加成功。
在这里插入图片描述

判断文档是否存在

@Test
public void testFetDoc() throws IOException {
    GetRequest getRequest = new GetRequest("test.index", "1");

    getRequest.fetchSourceContext(new FetchSourceContext(false));
    getRequest.storedFields("_none_");
    boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
    System.out.println(exists);  // true
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

执行单元测试,控制台输出true,表示之前添加的索引是存在的。

获取文档信息:

void testGetDocInfo() throws IOException {
    GetRequest getRequest = new GetRequest("test.index", "1");
    GetResponse getResponse = restHighLevelClient.get(getRequest,
                                                      RequestOptions.DEFAULT);
    System.out.println(getResponse.getSourceAsString());
    System.out.println(getResponse);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

执行单元测试,控制台输出:

{"age":18,"name":"kobe"}
{"_index":"test.index","_type":"_doc","_id":"1","_version":2,"_seq_no":1,
 "_primary_term":1,"found":true,"_source":{"age":18,"name":"kobe"}}
  • 1
  • 2
  • 3

更新文档:

@Test
void testUpdateRequest() throws IOException {
    UpdateRequest updateRequest = new UpdateRequest("test.index","1");
    updateRequest.timeout("1s");
    Person person = Person.builder().name("James").age(34).build();
    updateRequest.doc(JSON.toJSONString(person),XContentType.JSON);
    UpdateResponse updateResponse = restHighLevelClient.update(updateRequest,
                                                              RequestOptions.DEFAULT);
    System.out.println(updateResponse.status());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

执行单元测试,观察elasticsearch中文档的情况,发现更新成功。
在这里插入图片描述

删除文档

@Test
void testDeleteRequest() throws IOException {
    DeleteRequest request = new DeleteRequest("test.index","1");
    request.timeout("1s");
    DeleteResponse deleteResponse = restHighLevelClient.delete(request,
                                                               RequestOptions.DEFAULT);
    System.out.println(deleteResponse.status());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

执行单元测试后,观察elasticsearch中索引的情况,发现此时test.index已经不在了,删除操作执行成功。
在这里插入图片描述

3.4 批量操作
3.4.1 批量添加
@Test
public void testBulkRequest() throws IOException{
    BulkRequest bulkRequest = new BulkRequest();
    bulkRequest.timeout("1s");

    List<Person> list = new ArrayList<>();
    Collections.addAll(list, new Person("Kobe", 18),
                       new Person("James", 34),
                       new Person("Ball", 24));

    for (int i = 0; i < list.size(); i++) {
        bulkRequest.add(new IndexRequest("test.index").id(" " + i + 1)
                        .source(JSON.toJSONString(list.get(i)),XContentType.JSON));
    }

    BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(bulkResponse.hasFailures());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

执行单元测试,查看elasticsearch可以看到所有的文档均添加到了test.index中。
在这里插入图片描述

3.4.2 批量查询
@Test
void testSearch() throws IOException {
    SearchRequest searchRequest = new SearchRequest("test.index");
    // 构建搜索条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.highlighter();
    // 查询条件,我们可以使用 QueryBuilders 工具来实现
    // QueryBuilders.termQuery 精确
    // QueryBuilders.matchAllQuery() 匹配所有
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", "18");
    //        // MatchAllQueryBuilder matchAllQueryBuilder =
    //        QueryBuilders.matchAllQuery();
    sourceBuilder.query(termQueryBuilder);
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest,
                                                               RequestOptions.DEFAULT);
    System.out.println(JSON.toJSONString(searchResponse.getHits()));
    System.out.println("=================================");
    for (SearchHit documentFields : searchResponse.getHits().getHits()) {
        System.out.println(documentFields.getSourceAsMap());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

执行单元测试,控制台输出

{"fragment":true,"hits":[{"fields":{},"fragment":false,"highlightFields":{},
                          "id":" 01","matchedQueries":[],"primaryTerm":0,"rawSortValues":[],
                          "score":1.0,"seqNo":-2,"sortValues":[],"sourceAsMap":{"name":"Kobe","age":18},
                          "sourceAsString":"{\"age\":18,\"name\":\"Kobe\"}",
                          "sourceRef":{"fragment":true},"type":"_doc","version":-1}],
 "maxScore":1.0,"totalHits":{"relation":"EQUAL_TO","value":1}}

=================================

{name=Kobe, age=18}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/860234
推荐阅读
相关标签
  

闽ICP备14008679号