elasticsearch的基础知识

一、.几个概念(对比关系型数据库)

1.索引(Index)

类比mysql的database,一个索引就是一个数据库。es将数据存储在一个或多个索引中。向索引写入文档或从索引中读取文档。

2.文档(document)

文档是es中的只要实体,数据搜索,就是对文档的搜索。文档由字段构成。从客户端角度看,文档是一个JSON对象

3.映射(mapping)

类似mysql中对于表结构的定义。对index中的元信息进行存储。例如如何将输入文本分割为词条,哪些词条被过滤等等。

4.类型(type)

一个索引可以有多个类型。例如一个索引下可以有文章类型,也可以有用户类型,也可以有评论类型。在一个索引中不能再创建多个类型,在以后的版本中将删除类型的整个概念。

在Elasticsearch 7.0.0或更高版本中创建的索引不再接受 _default_映射。在6.x中创建的索引将继续像以前一样在Elasticsearch 6.x中运行。在7.0中的API中不推荐使用类型,对索引创建,放置映射,获取映射,放置模板,获取模板和获取字段映射API进行重大更改。

5.节点(node)

一个es服务实例称为一个节点

6.集群(cluster)

多个节点组成一个集群。

这个集群名称必须是唯一的,因为集群的节点是通过集群名称来加入集群的

7.分片(shard)和副本

索引可能存储大量数据,这些数据可能会c超出单个节点的硬件限制。例如,占用1TB磁盘空间的10亿个文档的单个索引可能不适合单个节点的磁盘,或者速度太慢,无法单独满足单个节点的搜索请求。

为了解决这个问题,ElasticSearch提供了将索引细分为多个片段(称为碎片)的能力。创建索引时,只需定义所需的碎片数量。每个分片(shard)本身就是一个完全功能性和独立的“索引”,可以托管在集群中的任何节点上。

为什么要分片?

它允许您水平拆分/缩放内容量

它允许您跨碎片(可能在多个节点上)分布和并行操作,从而提高性能/吞吐量

为什么要有副本?

当分片/节点发生故障时提供高可用性。因此,需要注意的是,副本分片永远不会分配到复制它的原始/主分片所在的节点上。

允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索。

可以在创建索引时为每个索引定义分片和副本的数量。创建索引后,您还可以随时动态更改副本的数量。您可以使用收缩和拆分API更改现有索引的分片数量,建议在创建索引时就考虑好分片和副本的数量。

默认情况下,ElasticSearch中的每个索引都分配一个主分片和一个副本,这意味着如果集群中至少有两个节点,则索引将有一个主分片和另一个副本分片(一个完整副本),每个索引总共有两个分片。

8.网关(mapping)

在es的工作过程中,关于集群状态,索引设置的各种信息都会被收集起来,并在网关中被持久化

二、操作速查

结构化搜索

请求格式: ///

GET http://{{es}}/_cat/health?v  集群健康状态

GET http://{{es}}/_cat/nodes?v 节点列表

GET http://{{es}}/_cat/indices?v 索引列表

PUT http://{{es}}/索引名?pretty 索引创建

DELETE http://{{es}}/索引名?pretty 索引删除 

PUT  http://{{es}}/索引名/_doc/数据ID?pretty 创建/替换文档,ID不一致时创建,ID一致时替换

POST http://{{es}}//索引名/_doc?pretty 无ID创建文档。生成随机ID

POST http://{{es}}/索引名/_update/数据ID?pretty  文档更新(先删除旧文档,再创建新文档,两次数据一致时,会不进行更新)

DELETE http://{{es}}/索引名/_doc/数据ID?pretty 文档删除

POST http://{{es}}/demo1/_bulk?pretty 文档批处理,注意:每行json要用\n换行

插入两份文档

{"index":{"_id":"1"}}

{"name": "John Doe" }

{"index":{"_id":"2"}}

{"name": "Jane Doe" }'   

更新文档1.删除文档2

{"update":{"_id":"1"}}

{"doc": { "name": "John Doe becomes Jane Doe" } }

{"delete":{"_id":"2"}} 

GET http://{{es}}/demo1/_doc/1?pretty 根据ID搜索文档

三、DSL操作

match_all:搜索索引中的所有文档

指定返回字段:_source

{ "query": { "match_all": {} }, "_source": ["account_number", "balance"]}

分页: from....size.....(未定义时,默认从0开始,取十条记录)

{ "query": { "match_all": {} }, "from": 10, "size": 10}

排序:sort

{ "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ]}

范围:range

range" : { "price" : { "gte" : 20, "lte" : 40 } }

gt: > 大于(greater than)

lt: < 小于(less than)

gte: >= 大于或等于(greater than or equal to)

lte: <= 小于或等于(less than or equal to)

注意基数数字和日期字段的索引方式使高效地范围计算成为可能。 但字符串却并非如此,要想对其使用范围过滤,Elasticsearch 实际上是在为范围内的每个词项都执行 term 过滤器,这会比日期或数字的范围过滤慢许多。字符串范围在过滤 低基数(low cardinality) 字段(即只有少量唯一词项)时可以正常工作,但是唯一词项越多,字符串范围的计算会越慢。

exists/missing 存在/缺失查询

{ "query" : { "constant_score" : { "filter" : { "exists" : { "field" : "tags" } } } } }

null, [] (空数组)和 [null]  等价

term 查询

term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串

{ "term": { "age": 26 }}

{ "term": { "date": "2014-09-01" }}

{ "term": { "public": true }}

{ "term": { "tag": "full_text" }}

注意:字段没有精确值的情况,而是一段文本字符串时,term匹配无法拿到期望值。原文本已被默认的 analyze API进行了拆词,如果需要精确匹配,需要在做mapping映射时,将该字段设置为  not_analyzed

 例如

"productID" : { "type" : "string", "index" : "not_analyzed" <3> }

索引一旦创建,无法更新mapping

包含,而不是相等一定要了解 term 和 terms 是 包含(contains) 操作,而非 等值(equals) (判断)。

如果我们有一个 term(词项)过滤器 { "term" : { "tags" : "search" } } ,它会与以下两个文档 同时匹配:

{ "tags" : ["search"] } 

{ "tags" : ["search", "open_source"] }  

这种情况下,精确匹配需要新增其他条件来辅助查询

terms 查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{"terms": {"tag": ["search","full_text","nosql"] }}

exists 查询和 missing 查询

exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:

{"exists":  {"field":"title"}}

match 条件查询

模糊匹配查询

{ "query": { "match": { "address": "mill" } }}

或语句查询:包含mill或lane

{ "query": { "match": { "address": "mill lane" } }}

短语查询

{ "query": { "match_phrase": { "address": "mill lane" } }}

bool查询

and查询

{ "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } }}

or查询

{ "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } }}

not 查询

{ "query": { "bool": { "must_not": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } }}

复合查询:

查询email字段中包含 business或 opportunity,并且 starred字段是true或者(folder为inbox并且spam不为true)的文档

{

        "bool": {

                "must": {

                                "match": { "email": "business opportunity" }},

                                "should": [

                                                    { "match": { "starred": true }},

                                                    { "bool": { 

                                                                    "must": { "match": { "folder": "inbox" }},

                                                                    "must_not": { "match": { "spam": true }}

                                                                  }

                                                    }

                                                  ],

                                    "minimum_should_match": 1

                                  }

        }

关于 minimum_should_match字段的作用

控制精度,在这里,要求should中至少满足一个

filter查询子句(过滤查询结果,不影响匹配分数)

{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } }}

全文搜索

控制精度

所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,但有多少 should 语句应该匹配呢? 默认情况下,没有 should 语句是必须匹配的,只有一个例外:那就是当没有 must 语句的时候,至少有一个 should 语句必须匹配 

指定必须匹配的词项数用来表示一个文档是否相关。我们可以将其设置为某个具体数字,更常用的做法是将其设置为一个百分数 

{ "query": { "match": { "title": { "query": "quick brown dog", "minimum_should_match": "75%" } } } }

当给定百分比的时候, minimum_should_match 会做合适的事情:在之前三词项的示例中, 75% 会自动被截断成 66.6% ,即三个里面两个词。无论这个值设置成什么,至少包含一个词项的文档才会被认为是匹配的。

提高/降低权重

以下查询要求content字段同时包含funll,text, search三个字段。同时,当content中包含elasticsearch或lucene时,有更高的相关

{

"query": {

            "bool": {

                    "must": {

                                "match": { "content": { "query": "full text search", "operator": "and" } } },

                           "should": [

                                       { "match": { "content": { "query": "Elasticsearch", "boost": 3  } }},

                                      { "match": { "content": { "query": "Lucene", "boost": 2} }}

                                          ]

                       }

              }

}

boost:大于1提权,取0-1降权

多字段搜索

dis_max 查询

不使用 bool 查询,可以使用 dis_max 即分离 最大化查询(Disjunction Max Query) 。分离(Disjunction)的意思是 或(or) ,这与可以把结合(conjunction)理解成 与(and) 相对应。分离最大化查询(Disjunction Max Query)指的是: 将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回 :

假设源数据:

{ "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." }

{ "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." }

elasticsearch的基础知识_第1张图片
dis_max查询使得第二个源数据获得更高的source

tie_breaker 参数

可以通过指定 tie_breaker 这个参数将其他匹配语句的评分也考虑其中

tie_breaker 参数提供了一种 dis_max 和 bool 之间的折中选择,

它的评分方式如下:

获得最佳匹配语句的评分 _score 。    

将其他匹配语句的评分结果与 tie_breaker 相乘。

对以上评分求和并规范化。 

tie_breaker 可以是 0 到 1 之间的浮点数,其中 0 代表使用 dis_max 最佳匹配语句的普通逻辑, 1 表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,但是合理值应该与零接近(处于 0.1 - 0.4 之间),这样就不会颠覆 dis_max 最佳匹配性质的根本。

elasticsearch的基础知识_第2张图片

multi_match 查询


elasticsearch的基础知识_第3张图片
 best_fields 类型是默认值,可以不指定。 如 minimum_should_match 或 operator 这样的参数会被传递到生成的 match 查询中。


参考文档:


.elasticsearch官方文档地址

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/getting-started-install.html

elasticsearch权威指南(版本比较老,部分操作在新版本上有变化)

https://wjw465150.github.io/Elasticsearch/#%E5%BA%8F%E8%A8%80

term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串

你可能感兴趣的:(elasticsearch的基础知识)