好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

搜索一文入门ElasticSearch(节点 分片 CRUD 倒排索引 分词)

ElasticSearch

ElasticSearch是非常重要的检索工具,利用分词、索引(倒排索引)、分词从众多检索工具中脱颖而出,本章是入门基础学习篇内容。

基本概念:索引、文档和REST Api

ElasticSearch是面向文档的,文档是所有可搜索数据的最小单位

日志文件中的日志项 一本电影的具体信息 / 一张唱片的详细信息 Mp3播放器的一首歌 / 一篇PDF文档中的具体内容

文档会被序列化成Josn格式,保存在ElasticSearch中

Json对象由字段组成 每个字段都有对应的字段类型(字符串/数值/布尔/日期/二进制/范围类型)

每个文档都有一个UniqueID

你可以自己指定ID

或者通过ElasticSearch自动生成

Json文档

一篇文档包含了一系列的字段 Json文档,格式灵活,不需要预先定义格式 字段的类型可以指定或通过ElasticSearch自动推算 支持数组、支持嵌套

文档的元数据

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
     "_index" : ".kibana_1" ,
     "_type" : "_doc" ,
     "_id" : "space:default" ,
     "_score" : 1.0 ,
     "_source" : {
         "space" : {
         "name" : "默认值" ,
         "description" : "这是您的默认空间!" ,
         "color" : "#00bfb3" ,
         "_reserved" : true
         },
         "type" : "space" ,
         "references" : [ ],
         "updated_at" : "2022-05-13T09:16:16.465Z"
     }
}
元数据,用于标注文档的相关信息 _index : 文档所属的索引名 _type : 文档所属的类型名 _id : 文档唯一ID _source : 文档的原始Json数据 _version : 文档的版本信息 _score : 相关性打分

索引

index :索引是文档的容器,是一类文档的结合 index体现了逻辑空间的概念,每个索引都有自己的Mapping定义,用于定义包含的文档的字段名和字段类型 Shard 体现了物理空间的概念,索引中的数据分散在Shard上 索引的Mapping与Settings Mapping定义文档的字段类型 Setting定义不同的数据分布
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//查看索引相关信息
GET kibana_sample_data_ecommerce
//查看索引的文档总数
GET kibana_sample_data_ecommerce/_count
//查看前 10 条文档,了解文档格式
POST kibana_sample_data_ecommerce/_search
{
}
//_cat indices API
//查看indices
GET /_cat/indices/kibana*?v&s=index
//查看状态为绿的索引
GET /_cat/indices?v&health=green
//按照文档个数排序
GET /_cat/indices?v&s=docs.count:desc
//查看具体的字段
GET /_cat/indices/kibana*?pri&v&h=health,index,pri,rep,docs.count,mt
//How much memory is used per index?
GET /_cat/indices?v&h=i,tm&s=tm:desc

分布式系统的可用性和扩展性

高可用性 服务可用性 :允许有节点停止服务 数据可用性 :部分节点丢失,不会丢失数据 可扩展性 请求量提升 / 数据的不断增长(将数据分布都所有接点上)

分布式特性

elasticsearch的分布式架构的好处 存储的水平扩容 提高系统的可用性,部分节点停止服务,整个集群的服务不受影响 elasticsearch的分布式架构 不同的集群通过不同的名字来区分,默认名字"elasticsearch" 通过配置文件修改,或者在命令行中 -E cluster.name=stark 进行设定 一个集群可以有一个或多个节点

节点

节点是elasticsearch的实例 本质上就是一个Java进程 一台机器上可以运行多个elasticsearch进程,但是生产环境一般建议一台机器上只运行一个elasticsearch实例 每一个节点都有名字,通过配置文件配置,或者启动的时候 -E node.name=node1指定 每一个节点在启动之后,会分配一个UID,保存在data目录下

分片

主分片,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上 一个分片是一个运行的Lucene的实例 主分片数在索引创建时指定,后续不允许修改,除非Reindex 副本 ,用以解决数据高可用的问题,分片是主分片的拷贝 副本分片数,可以动态调整 增加副本数,还可以在一定程度上提高服务的可用性
?
1
2
3
4
5
6
{
     "settings" : {
         "number_of_shards" : 1 ,
         "number_of_replicas" : 1
     }
}

查看集群的健康状况

Green - 主分片与副本都正常分配 Yellow - 主分片全部正常分配,有副本分片未能正常分片 Red - 有主分片未能分配

CRUD

1.使用PostMan创建一个名字叫stark的索引

?
1
2
3
4
5
6
7
http:// 127.0 . 0.1 : 9200 /stark?pretty
// 返回值
{
     "acknowledged" : true ,
     "shards_acknowledged" : true ,
     "index" : "stark"
}

文档的CRUD

Type名,约定都用_doc Create ,如果ID已经存在,会失败 Index ,如果ID不存在,创建新的文档。否则先删除现有文档,再创建新的文档,版本会增加。 Update ,文档必须已经存在,更新只会对相应字段做增量修改。

Create 一个文档

支持自动生成文档ID和指定文档ID两种方式:

使用 POST /indexName/_doc ,系统会自动生成Document ID 使用 PUT /indexName/_create/ID 创建时,URI中显示指定 _create ,此时如果该ID的文档已经存在,操作失败

GET 一个文档

GET http://127.0.0.1:9200/IndexName/_doc/ID

找到文档,返回Http 200 文档元信息,同一个ID的文档,即使被删除,Version号也会不断增加 _source 中默认包含了文档的所有原始信息 找不到文档,返回Http 404

Index 文档

?
1
2
3
4
PUT IndexName/_doc/ 1
{
     "tags" :[ "name" , "age" , "sex" ]
}

Index和Create不一样的地方:如果文档存在,就索引新的文档。否则现有文档会被删除,新的文档被索引,版本信息(Version) + 1。

Update 文档

Update方法不会删除原来的文档,而是实现真正的数据更新,POST方法 ,Payload需要包含在doc中。

?
1
2
3
4
5
6
POST IndexNmae/_update/ 1
{
     "doc" :{
         "albums" :[ "aaa" , "bbb" ]
     }
}

删除文档

DELETE IndexName/_doc/ID

Bulk API / 批量读取 mGet / 批量查询 msearch

Bulk Api 支持在一次Api调用中,对不同的索引进行操作,支持四种类型操作,Index\Create\Update\Delete。

可以在URI中指定Index,也可以在请求的Payload中进行,操作单挑操作失败,并不影响其他操作,返回结果包括了每一条操作执行的结果。

?
1
2
3
4
5
6
7
8
9
10
11
//对同一个索引进行操作
POST /IndexName/_doc/_bulk
//对不同的索引进行操作
POST _bulk
{ "index" : { "_index" : "test" , "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test" , "_id" : "2" } }
{ "create" : { "_index" : "test2" , "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : { "_id" : "1" , "_index" : "test" } }
{ "doc" : { "field2" : "value2" } }

mGet批量操作,可以减少网络链接所产生的开销,提高性能。

?
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
#URI中指定index
GET /IndxName/_mget
{
     "docs" : [
         {
             "_id" : "1"
         },
         {
             "_id" : "2"
         }
     ]
}
//对不同的索引进行操作
GET /_mget
{
     "docs" : [
         {
             "_index" : "test" ,
             "_id" : "1"
         },
         {
             "_index" : "test" ,
             "_id" : "2"
         }
     ]
}

批量查询 msearch

?
1
2
3
4
5
// msearch 操作
POST kibana_sample_data_ecommerce/_msearch
{ "query" : { "match_all" : {}}, "size" : 1 }
{ "index" : "kibana_sample_data_flights" }
{ "query" : { "match_all" : {}}, "size" : 2 }

倒排索引

倒排索引的核心组成

倒排索引包含两个部分 单词词典,记录所有文档的单词,记录单词到倒排列表的关联关系 单词词典一般比较大,可以通过B+树或哈希拉链法实现,以满足高性能的插入和查询 倒排列表,记录了单词对应的文档结合,由倒排索引组成 倒排索引项 文档ID 词频TF - 该单词在文档中出现的次数,用于相关性评分 位置,单词在文档中分词的位置,用于语句搜索 偏移,记录单词的开始结束位置,实现高亮显示

Es的倒排索引

Es的Json文档中的每个字段,都有自己的倒排索引 可以指定对某些字段不做索引 优点:节省存储空间 缺点:字段无法被搜索

Analysis 与 Analyzer

Analysis,文本分析是把全文本转换成一系列单词(term / token)的过程,也叫分词。 Analysis 是通过 Analyzer 来实现的,可使用elasticsearch内置的分析器 / 或者按需定制化分析器。 除了在数据写入时转换词条,匹配Query语句时候也需要用相同的分析器对查询进行查询语句进行分析。

Analyzer的组成

分词器是专门处理分词的组件,Analyzer由三部分组成: ① 针对原始文本处理,例如去除html ② 按照规则切分单词 ③ 将切分的单词进行加工,小写,删除stopworlds,增加同义词

Search Api

URI Search ,在URL中使用查询参数 Request Body Search ,使用es提供的,基于Json格式的更加完备的Query Domain Specific Language(DSL)

1.指定查询的索引

集群上所有的索引:

?
1
2
3
4
GET /_search //集群上所有的索引
GET /Index 1 /_search  //index 1
GET /Index 1 ,Index 2 /_search  //index 1 和index 2
GET /index*/_search  //以index开头的索引

2.URI查询

使用"q",指定字符串查询 "query string syntax",KV键值对

用q表示查询内容,搜索叫做stark的客户 GET /IndexName/_search?q=keyName:stark

3.Request Body

Request Body 支持 POST/GET两种方法,-H代表的是header参数 -d 代表的是body的请求参数。

?
1
2
3
4
5
6
7
8
9
10
curl -XGET "http://127.0.0.1:9200/IndexName/_search"
-H 'Content-Type:application/json'
-d
'
{
  "query" :{
      "match_all" :{}
  }   
}
'

4.搜索Response

搜索Response有几个关键的描述需要在这里解释一下:

took: 花费的时间 total: 符合条件的总文档数 hits:结果集,默认前10个文档 _index:索引名 _id:文档的ID _score: 相关度评分 _source:文档原始信息

URI Search详解

指定字段查询 Vs 泛查询

q是关键字,df是指定字段,泛查询就是查询所有字段中包含关键字的结果

?
1
2
3
4
5
6
7
8
9
10
11
//指定字段
GET /IndexName/_search?q= 2020 &amp;df=title
GET /IndexName/_search?q=title: 2020
{
     "profile" : "true"
}
//泛查询
GET /IndexName/_search?q= 2020
{
     "profile" : "true"
}

Term Vs Phrase

Hello World 等效于 Hello Or World

"Hello World",等效于Hello AND World 。Phrase查询,还要求前后顺序保持一致

分组和引号

title:(Hello AND World) title = "Hello World"
?
1
2
3
4
5
6
7
8
9
10
//分组,Bool查询
GET /IndexName/_search?q=title:(Hello World)
{
     "profile" : "true"
}
//泛查询
GET /IndexName/_search?q=title:Hello World
{
     "profile" : "true"
}

布尔操作 、分组

布尔操作 AND / OR / NOT 或者 && / || / ! 必须大写 title:(Hello NOT World) 分组 表示 must 表示 must_not title:(+Hello -World)
?
1
2
3
4
5
6
7
8
9
10
//检索title里有Hello ,没有World的词条
GET /IndexName/_search?q=title:(Hello NOT World)
{
     "profile" : "true"
}
//检索title里必须有Hello ,必须没有World的词条
GET /IndexName/_search?q=title:(+Hello -World)
{
     "profile" : "true"
}

范围查询 、算术符号

URI Search支持范围查询和算术符号查询。

范围查询 区间表示:[]闭区间,{}开区间 year:{2019 TO 2020} year:[* TO 2020] 算数符号 year:> 2020 year:(>2010 && < 2020) year:(+>2010 && +< 2020)
?
1
2
3
4
GET /IndexName/_search?q=year:> 2020
{
     "profile" : "true"
}

通配符查询 、正则表达式 、模糊匹配与近似查询

通配符查询 、正则表达式 、模糊匹配与近似查询效率低,占用内存大,不建议使用,这部分大家有个了解就好。

以上就是搜索一文入门ElasticSearch(节点 分片 CRUD 倒排索引 分词)的详细内容,更多关于ElasticSearch搜索入门的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/7210918245993709605

查看更多关于搜索一文入门ElasticSearch(节点 分片 CRUD 倒排索引 分词)的详细内容...

  阅读:13次