Elasticsearch8入门

作者: pq217 | 来源:发表于2022-10-09 21:33 被阅读0次

    版本

    8.4

    安装

    windows本地安装,直接下载zip包解压即可
    windows安装官方教程
    启动

    .\bin\elasticsearch.bat
    

    elasticsearch本地就跑起来了

    docker安装更方便

    配置

    主配置文件在config下的elasticsearch.yml

    elasticsearch默认是要校验身份的,可以暂时去掉xpack.security.enabled修改为false

    # Enable security features
    xpack.security.enabled: false
    

    配置可跨域(否则跨域不可访问)

    http.cors.enabled: true
    http.cors.allow-origin: "*"
    http.host: 0.0.0.0
    
    elasticsearch.yml

    重启之后既可以开始使用了,简单测试一下是否正常

    $ curl localhost:9200
    
    localhost:9200

    elasticsearch本地就搭建好了

    客户端

    就像mysql有navicat等客户端,用起来方便又直观,elasticsearch也有一个勉强可用的客户端
    elasticsearch-head,是一个前端的代码,下载下来,运行也很简单: npm install安装依赖,npm run start运行,打开界面即可http://localhost:9100/

    http://localhost:9100

    但从实际效果上看,客户端提供的功能非常少,也不适合初学者学习

    概念

    Elasticsearch可以看做一个便于搜索的数据库,相比传统关系型数据库如下

    Mysql ‐> Databases ‐> Tables ‐> Rows ‐> Columns
    Elasticsearch ‐> Indices ‐> Types ‐> Documents ‐> Fields

    Elasticsearch 8 已经删除了Types,所以现在的层级应该是

    Elasticsearch ‐> Indices ‐> Documents ‐> Fields

    Index

    索引,相当于mysql中的一个数据表(原来有type时它相当于数据库,type相当于数据表,现在es8取消了type,index当做一个数据表来理解方便一点)

    Documents

    一条存储的数据,相当于mysql的一条数据

    Fields

    字段,类似mysql的子墩

    API

    Elasticsearch牛在封装了Lucene,提供了强大的搜索功能,同时对外暴露Restful Api使其易于对接,接下来就通过调用api来实现一个小功能:

    存储一个网站的文章,并可以通过标题和内容智能检索

    第一步,创建文章索引

    就好比在mysql中创建一个文章表article,包含三个字段id,title,content

    curl --location --request PUT 'http://127.0.0.1:9200/article' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "mappings": {
            "properties": {
                "id": {
                    "type": "long",
                    "index": false
                },
                "title": {
                    "type": "text",
                    "analyzer": "standard"
                },
                "content": {
                    "type": "text",
                    "analyzer": "standard"
                }
            }
        }
    }'
    

    关于索引的文档,可以参考Index APIs

    第二步,添加几个测试文章

    curl --location --request POST 'http://127.0.0.1:9200/article/_doc/1' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "id": 1,
        "title": "小李飞刀",
        "content": "小李飞刀,例无虚发"
    }'
    

    其中url上article代表索引名,_doc是默认,1代表id,如果没有则自动生成,请求体即文章的标题和内容

    多增加几个文章进行测试

    article

    关于文档的文档,可以参考Document APIs

    第三步,检索

    测试数据准备好了,接下来进行搜索测试,我们搜索"刀",并希望所有带"刀"字样的都搜出来,相当于sql的

    WHERE  (title like '%刀%' OR content like '%刀%')
    

    写法如下,使用布尔过滤器

    curl --location --request GET 'http://localhost:9200/article/_search' \
    --header 'Content-Type: application/json' \
    --data-raw '{
      "query": { 
        "bool": { 
          "should": [
            { "match": { "title":   "刀" }},
            { "match": { "content": "刀" }}
          ]
        }
      }
    }'
    

    最终输出结果如下

    可以看到实现了我们的需求,带“刀”的数据都被查了出来
    再搜索一下"刀剑"

    刀剑

    可以看到相关的都被查出,这种查询在mysql是做不到的

    这种搜索查询的语法是ES自己指定的,可以支持很多复杂的查询方式,而且有一个很不错的中文文档,文档可能有些过期,但大部分还好,并且人性化的对照了mysql的场景

    整合springboot

    • 如果想简单粗暴的代码调用es,其实使用HttpClient也可以,毕竟都是http接口,道理很简单,但写的代码肯定很费劲

    • 为了方便用户使用,es肯定是要提供sdk的,即elasticsearch-rest-high-level-client,专门针对es的客户端,使用起来肯定更方便

    • 为了使用更加方便,spring在elasticsearch-client基础上再次封装出了spring-data-elasticsearch,进一步的封装使spring用户调用es非常方便

    spring每个阶段会根据spring的当前版本以及es的版本在不同时期适配不同的依赖包,这就导致每个spring-data-elasticsearch版本肯定会有一个适用的spring版本及es版本,当前的关系如下

    spring-data-elasticsearch

    很不幸,当前好像并没有适配es8的版本,且我自己用的springboot版本为2.3.x,所以只能尝试使用4.0.x的spring-data-elasticsearch,考虑到这种牛逼项目都有低版本适配,问题应该也不大

    引入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    
    配置Elasticsearch

    主要是配置服务器地址,超时时间什么的,创建一个RestHighLevelClient客户端的bean

    @Configuration
    public class ElasticsearchClientConfig extends AbstractElasticsearchConfiguration {
       
        // 地址
        @Value("${spring.data.elasticsearch.host}")
        private String host;
        // 端口
        @Value("${spring.data.elasticsearch.port}")
        private String port;
    
        @Override
        @Bean
        public RestHighLevelClient elasticsearchClient() {
            final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                    .connectedTo(host + ":" + port)
                    .build();
            return RestClients.create(clientConfiguration).rest();
        }
    }
    

    到此spring的es配置结束,接下来就是增删查改,用过jpa的会发现基本一个套路

    定义实体,映射到索引

    创建一个实体Book并映射到es的索引book

    @Data
    @Document(indexName = "book",createIndex = true) // 映射book索引
    public class Book {
         // 主键标识
        @Id
        @Field(type = FieldType.Long)
        private Long id;
        @Field(analyzer="standard")
        private String title;
        @Field(analyzer="standard")
        private String content;
    }
    
    定义仓库
    public interface BookRepositoryImpl extends ElasticsearchRepository<Book, Long> {
        List<Book> findByTitleOrContent(String title, String content);
    }
    

    这个仓库的接口定义好之后,就可以通过spring注入,注入对象默认包含方法

    • save 保存,新增/修改
    • findAll 查询,带分页
    • delete 删除
    • 等等

    也可以自己定义方法,主要有两种方式
    一、直接从方法名称派生查询
    例如上面的findByTitleOrContent就会自动转化为根据标题或内容查询
    二、使用@Query注解自定义的查询
    例如

    interface BookRepository extends ElasticsearchRepository<Book, String> {
        @Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
        Page<Book> findByName(String name,Pageable pageable);
    }
    

    使用过jpa应该再熟悉不过了,功能十分强大,可以参考官方文档

    使用仓库

    这就非常简单了,写个小例子

    @Autowired
    private BookRepository bookRepository;
    
    public void test() {
        Book book = new Book();
        book.setId(1L);
        book.setTitle("雪中悍刀行");
        book.setContent("你是我的白月光,我是你的小砒霜");
        // 新增文档
        bookRepository.save(book);
        // 查询所有
        Iterable<Book> all = bookRepository.findAll();
        for (book po : all) {
    
        }
        // 通过标题或内容查询带"刀"的文档
        List<Book> hits = bookRepository.findByTitleOrContent("刀", "刀");
    }
    
    修改版本不兼容问题

    跑了一下还出出问题,报错type不能为null,原因是es8已取消type,而我们低版本客户端还是会校验type必须存在,导致运行出错,报错点如下


    type不能为null

    修改办法:
    没找到太好的解决办法,只是粗暴的重写了DocWriteResponse类


    type不能为null解决

    相关文章

      网友评论

        本文标题:Elasticsearch8入门

        本文链接:https://www.haomeiwen.com/subject/klzgartx.html