一、.几个概念(对比关系型数据库)
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." }
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 最佳匹配性质的根本。
multi_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 的字符串