elasticsearch介绍与快速应用

序言

同步数据方式:
1.可以用通过发送mq消息,调用es的api进行同步数据
2.用其他工具进行库级别同步

1.前言

  • 我们选择最新操作elasticsearch方法,通过java api client 操作
  • java 8 或者更新版本
  • elasticsearch版本7.17
  • 支持jackson 或者JSON-B库

2.定义

Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。 能够达到实时搜索,稳定,可靠,快速,安装使用方便。
客户端支持Java、.NET(C#)、PHP、Python、Ruby等多种语言 官方网站: https://www.elastic.co/
下载地址:https://www.elastic.co/cn/start

3.应用场景

  • 复杂连表查询
  • 模糊查询

4.核心概念

4.1索引

一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户数据 的索引,另一个产品目录的索引,还有一个订单数据的索引
一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这 个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字

4.2映射mapping

ElasticSearch中的映射(Mapping)用来定义一个文档
mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认 值、分词器、是否被索引等等,这些都是映射里面可以设置的

4.3字段filed

相当于是数据表的字段|列

4.4字段类型type

每一个字段都应该有一个对应的类型,例如:Text、Keyword、Byte等

4.5文档document

一个文档是一个可被索引的基础信息单元,类似一条记录。文档以JSON(Javascript Object Notation)格式来表示;

4.6主要字段类型

字符串:string,string类型包含 text 和 keyword。
text:该类型被用来索引长文本,在创建索引前会将这些文本进行分词,转化为
词的组合,建立索引;允许es来检索这些词,text类型不能用来排序和聚合。
keyword:该类型不能分词,可以被用来检索过滤、排序和聚合,keyword类型不 可用text进行分词模糊检索。
数值型:long、integer、short、byte、double、float 日期型:date 布尔型:boolean

5.安装

https://blog.csdn.net/GZ946/article/details/124862518

6.客户端基本命令操作

  • 创建索引
    举例: PUT /es_db
  • 查询索引
    举例: GET /es_db
  • 删除索引
    举例: DELETE /es_db
  • 新增索引
  • PUT /es_db/_doc/1
    {
    “name”: “张三”,
    “sex”: 1,
    “age”: 25,
    “address”: “广州天河公园”,
    “remark”: “java developer”
    }

7.对已存在的mapping映射进行修改

  • 如果要推倒现有的映射, 你得重新建立一个静态索引
  • 然后把之前索引里的数据导入到新的索引里
  • 删除原创建的索引
  • 为新索引起个别名, 为原索引名
POST _reindex
{
"source": {
"index": "db_index"
},
"dest": {
"index": "db_index_2"
}
}
DELETE /db_index
PUT /db_index_2/_alias/db_index

8.Elasticsearch重要工作流程

8.1Elasticsearch文档写入原理

在这里插入图片描述

1.选择任意一个DataNode发送请求,例如:node2。此时,node2就成为一个 coordinating node(协调节点)
2.计算得到文档要写入的分片 shard = hash(routing) % number_of_primary_shards routing 是一个可变值,默认是文档的 _id
3.coordinating node会进行路由,将请求转发给对应的primary shard所在的 DataNode(假设primary shard在node1、replica shard在node2)
4.node1节点上的Primary Shard处理请求,写入数据到索引库中,并将数据同步到 Replica shard
5.Primary Shard和Replica Shard都保存好了文档,返回client

8.2Elasticsearch检索原理

在这里插入图片描述

client发起查询请求,某个DataNode接收到请求,该DataNode就会成为协调节点 (Coordinating Node)
协调节点(Coordinating Node)将查询请求广播到每一个数据节点,这些数据节 点的分片会处理该查询请求
每个分片进行数据查询,将符合条件的数据放在一个优先队列中,并将这些数据 的文档ID、节点信息、分片信息返回给协调节点
协调节点将所有的结果进行汇总,并进行全局排序 协调节点向包含这些文档ID的分片发送get请求,对应的分片将文档数据返回给协
调节点,最后协调节点将数据返回给客户端

9.Elasticsearch准实时索引实现

1 溢写到文件系统缓存
当数据写入到ES分片时,会首先写入到内存中,然后通过内存的buffer生成一个
segment,并刷到文件系统缓存中,数据可以被检索(注意不是直接刷到磁盘) ES中默认1秒,refresh一次
2写translog保障容错
在写入到内存中的同时,也会记录translog日志,在refresh期间出现异常,会根
据translog来进行数据恢复 等到文件系统缓存中的segment数据都刷到磁盘中,清空translog文件
3 flush到磁盘
ES默认每隔30分钟会将文件系统缓存的数据刷入到磁盘
4 segment合并
Segment太多时,ES定期会将多个segment合并成为大的segment,减少索引查询时
IO开销,此阶段ES会真正的物理删除(之前执行过的delete的数据)
在这里插入图片描述

10.快速应用

10.1Maven配置

<project>
  <dependencies>

    <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>8.6.0</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.12.3</version>
    </dependency>

  </dependencies>
</project>

10.2配置

@Configuration
public class ElasticSearchClientConfig  {
    @Bean
    public ElasticsearchClient elasticsearchClient() {

        // Create the low-level client
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials("elsearch", "Gz150983"));

        RestClient client = RestClient.builder(new HttpHost("192.168.136.128", 9200, "http"))
                .setHttpClientConfigCallback(httpAsyncClientBuilder -> {
                    httpAsyncClientBuilder.disableAuthCaching();
                    return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                }).build();

        // Create the transport with a Jackson mapper
        ElasticsearchTransport transport = new RestClientTransport(client,new JacksonJsonpMapper());
        // And create the API client
        ElasticsearchClient ElasticsearchClient = new ElasticsearchClient(transport);
        return ElasticsearchClient;
    }

}

10.3调用案例

官方API
介绍https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-multi-search.html

@SpringBootTest
@RunWith(SpringRunner.class)
class EsApplicationTests {
    @Autowired
    private ElasticsearchClient client;

    /**
     * 创建索引
     */
    @Test
    public void createIndex() throws IOException {
        //执行创建索引操作并返回结果
       CreateIndexResponse createIndexResponse = client.indices().create(c->c.index("test"));
       System.out.println(createIndexResponse);

    }

    /**
     * 新的document
     */
    @Test
    public void saveDocument() throws IOException {
        //执行创建索引操作并返回结果
        TestDTO testDTO=new TestDTO();
        testDTO.setBrand("d");
        testDTO.setId(2L);
        testDTO.setCategory("测试");
        testDTO.setImages("测试路径URL");
        testDTO.setPrice(2.0);
        testDTO.setTitle("弟弟");
        CreateResponse createResponse = client.create(e->e.index("test").id("1003").document(testDTO));
        System.out.println(createResponse);

    }
    @Test
    public void getDocument() throws IOException {
        //执行创建索引操作并返回结果
        // 构建查询请求
        GetResponse<TestDTO> response = client.get(e -> e.index("test").id("1003"), TestDTO.class);
        System.out.println(response.source().toString());
    }
}

10.4问题集锦

  • ClassNotFoundException: jakarta.json.spi.JsonProvider
  <dependency>
      <groupId>jakarta.json</groupId>
      <artifactId>jakarta.json-api</artifactId>
      <version>2.0.1</version>
    </dependency>

10.5示例代码

https://gitee.com/GZ-jelly/gz-common.git

10.6Elasticsearch关联关系如何存储

博客参考https://blog.csdn.net/laoyang360/article/details/88784748
官方参考:https://www.elastic.co/guide/en/elasticsearch/guide/current/relations.html

关联关系仍然非常重要。某些时候,我们需要缩小扁平化和现实世界关系模型的差异。
以下四种常用的方法,用来在 Elasticsearch 中进行关联数据的管理:

  • 应用端关联

这是普遍使用的技术,即在应用接口层面来处理关联关系。 针对星球问题实践, 存储层面:独立两个索引存储。 实际业务层面分两次请求:
第一次查询返回:Top5中文姓名和成绩; 根据第一次查询的结果,第二次查询返回:Top5中文姓名和英文姓名;
将第一次查询结果和第二次查询结果组合后,返回给用户。 即:实际业务层面是进行了两次查询,统一返回给用户。用户是无感知的。
适用场景:数据量少的业务场景。 优点:数据量少时,用户体验好。 缺点:数据量大,两次查询耗时肯定会比较长,影响用户体验。
引申场景:关系型数据库和ES 结合,各取所长。将关系型数据库全量同步到 ES 存储,不做冗余存储。 如前所述:ES 擅长的是检索,而
MySQL 才擅长关系管理。所以可以考虑二者结合,使用 ES 多索引建立相同的别名,针对别名检索到对应 ID 后再回 MySQL
查询,业务层面通过关联 ID join 出需要的数据。

  • 宽表冗余存储

对应于官方文档中的“Data denormalization”,官方直接翻译为:“非规范化你的数据”,总感觉规范化是什么鬼,不好理解。
通俗解释就是:冗余存储,对每个文档保持一定数量的冗余数据可以在需要访问时避免进行关联。 这点通过logstash
同步关联数据到ES时,通常会建议:先通过视图对Mysql数据做好多表关联,然后同步视图数据到ES。此处的视图就是宽表。
针对星球问题实践:姓名、英文名、成绩两张表合为一张表存储。 适用场景:一对多或者多对多关联。
优点:速度快。因为每个文档都包含了所需的所有信息,当这些信息需要在查询进行匹配时,并不需要进行昂贵的关联操作。
缺点:索引更新或删除数据,应用程序不得不处理宽表的冗余数据; 由于冗余存储,导致某些搜索和聚合操作可能无法按照预期工作。

  • 嵌套文档(Nested)存储

Nested类型是ES Mapping定义的集合类型之一,它是比object类型更NB的支持独立检索的类型。
举例:有一个文档描述了一个帖子和一个包含帖子上所有评论的内部对象评论。可以借助 Nested 实现。
实践注意1:当使用嵌套文档时,使用通用的查询方式是无法访问到的,必须使用合适的查询方式(nested query、nested
filter、nested facet等),很多场景下,使用嵌套文档的复杂度在于索引阶段对关联关系的组织拼装。
推荐实践:https://blog.csdn.net/laoyang360/article/details/82950393 实践注意2:
index.mapping.nested_fields.limit 缺省值是50。即:一个索引中最大允许拥有50个nested类型的数据。
index.mapping.nested_objects.limit
缺省值是10000。即:1个文档中所有nested类型json对象数据的总量是10000。 适用场景:1
对少量,子文档偶尔更新、查询频繁的场景。 如果需要索引对象数组并保持数组中每个对象的独立性,则应使用嵌套 Nested 数据类型而不是对象
Oject 数据类型。 优点:nested文档可以将父子关系的两部分数据(举例:博客+评论)关联起来,可以基于nested类型做任何的查询。
缺点:查询相对较慢,更新子文档需要更新整篇文档。

  • 父子文档存储

注意:6.X之前的版本的父子文档存储在相同索引的不同type中。而6.X之上的版本,单索引下已不存在多type的概念。父子文档Join的都是基于相同索引相同type实现的。
Join类型是ES Mapping定义的类型之一,用于在同一索引的文档中创建父/子关系。
关系部分定义文档中的一组可能关系,每个关系是父名称和子名称。
实践参考:https://blog.csdn.net/laoyang360/article/details/79774481
适用场景:子文档数据量要明显多于父文档的数据量,存在1 对多量的关系;子文档更新频繁的场景。 举例:1
个产品和供应商之间是1对N的关联关系。 当使用父子文档时,使用has_child 或者has_parent做父子关联查询。
优点:父子文档可独立更新。 缺点:维护Join关系需要占据部分内存,查询较Nested更耗资源。

  • 小结

在Elasticsearch开发实战中对于多表关联的设计要突破关系型数据库设计的思维定式。
不建议在es做join操作,parent-child能实现部分功能,但是它的开销比较大,如果可能,尽量在设计时使用扁平的文档模型。
尽量将业务转化为没有关联关系的文档形式,在文档建模处多下功夫,以提升检索效率。 Nested&Join父子文选型必须考虑性能问题。
nested 类型检索使得检索效率慢几倍,父子Join 类型检索会使得检索效率慢几百倍。
以上内容,实际官方文档都有明确的描述。我把内容加上自己的理解,作了精炼和解读。
再次强调:第一手资料的重要性。但本着“再显而易见的道理,也有N多人不知道”的原则,一定要读英文官方文档,加深认知理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫果冻

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值