ElasticSearch基本操作
看别人的博客不如看书来的全面
ES权威指南中文版
https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html
ES有两种查询方式
一种是 “轻量的” 查询字符串 版本,要求在查询字符串中传递所有的 参数,另一种是更完整的 请求体 版本,要求使用 JSON 格式和更丰富的查询表达式作为搜索语言
在公司使用的是带请求体的curl查询
倒排索引这个看着挺有意思的
https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html
检索过程的原理
自定义域映射
尽管在很多情况下基本域数据类型 已经够用,但你经常需要为单独域自定义映射 ,特别是字符串域。自定义映射允许你执行下面的操作:
全文字符串域和精确值字符串域的区别
使用特定语言分析器
优化域以适应部分匹配
指定自定义数据格式
还有更多
域最重要的属性是 type 。对于不是 string 的域,你一般只需要设置 type :
{
“number_of_clicks”: {
“type”: “integer”
}
}
默认, string 类型域会被认为包含全文。就是说,它们的值在索引前,会通过 一个分析器,针对于这个域的查询在搜索前也会经过一个分析器。
string 域映射的两个最重要 属性是 index 和 analyzer 。
index编辑
index 属性控制怎样索引字符串。它可以是下面三个值:
analyzed
首先分析字符串,然后索引它。换句话说,以全文索引这个域。
以全文 analyzed 字段排序会消耗大量的内存。
not_analyzed
索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
no
不索引这个域。这个域不会被搜索到。
string 域 index 属性默认是 analyzed 。如果我们想映射这个字段为一个精确值,我们需要设置它为 not_analyzed :
{
“tag”: {
“type”: “string”,
“index”: “not_analyzed”
}
}
注意
其他简单类型(例如 long , double , date 等)也接受 index 参数,但有意义的值只有 no 和 not_analyzed , 因为它们永远不会被分析。
ElasticSearch组合查询
https://www.cnblogs.com/yjf512/p/4897294.html
过滤(filtering)的目标是减少那些需要通过评分查询(scoring queries)进行检查的文档。
同时filter会将查询的结果缓存到内存中以便快速进行读取,使查询性能更优。
如何选择查询与过滤?
通常的规则是,使用 查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(filters)。
match,term,terms,rannge,exists,missing查询
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_most_important_queries.html
搜索API的最基础的形式是没有指定任何查询的空搜索 ,它简单地返回集群中所有索引下的所有文档:
查询结果解释
原文:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/empty-search.html
GET /_search
拷贝为 CURL在 SENSE 中查看
返回的结果(为了界面简洁编辑过的)像这样:
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
hits
返回结果中最重要的部分是 hits ,它 包含 total 字段来表示匹配到的文档总数,并且一个 hits 数组包含所查询结果的前十个文档。
在 hits 数组中每个结果包含文档的 _index 、 _type 、 _id ,加上 _source 字段。这意味着我们可以直接从返回的搜索结果中使用整个文档。这不像其他的搜索引擎,仅仅返回文档的ID,需要你单独去获取文档。
每个结果还有一个 _score ,它衡量了文档与查询的匹配程度。默认情况下,首先返回最相关的文档结果,就是说,返回的文档是按照 _score 降序排列的。在这个例子中,我们没有指定任何查询,故所有的文档具有相同的相关性,因此对所有的结果而言 1 是中性的 _score 。
max_score 值是与查询所匹配文档的 _score 的最大值。
took
took 值告诉我们执行整个搜索请求耗费了多少毫秒。
shards
_shards 部分 告诉我们在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。正常情况下我们不希望分片失败,但是分片失败是可能发生的。如果我们遭遇到一种灾难级别的故障,在这个故障中丢失了相同分片的原始数据和副本,那么对这个分片将没有可用副本来对搜索请求作出响应。假若这样,Elasticsearch 将报告这个分片是失败的,但是会继续返回剩余分片的结果。
timeout
timed_out 值告诉我们查询是否超时。默认情况下,搜索请求不会超时。 如果低响应时间比完成结果更重要,你可以指定 timeout 为 10 或者 10ms(10毫秒),或者 1s(1秒):
验证查询
GET /_search?timeout=10ms
在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。
警告
应当注意的是 timeout 不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接。在后台,其他的分片可能仍在执行查询即使是结果已经被发送了。
使用超时是因为 SLA(服务等级协议)对你是很重要的,而不是因为想去中止长时间运行的查询。
对于合法查询,使用 explain 参数将返回可读的描述,这对准确理解 Elasticsearch 是如何解析你的 query 是非常有用的:
GET /_validate/query?explain
{
“query”: {
“match” : {
“tweet” : “really powerful”
}
}
}
相关性排序准则
检索词频率:
检索词 honeymoon
在这个文档的 tweet
字段中的出现次数。
反向文档频率:
检索词 honeymoon
在索引上所有文档的 tweet
字段中出现的次数。
字段长度准则:
在这个文档中, tweet
字段内容的长度 – 内容越长,值越小。
假定我们想要结合使用 date 和 _score 进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序:
多级排序
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
拷贝为 CURL在 SENSE 中查看
排序条件的顺序是很重要的。结果首先按第一个条件排序,仅当结果集的第一个 sort 值完全相同时才会按照第二个条件进行排序,以此类推。
查询索引状态:
curl ‘http://ip:port/_cat/indices?v’
查询所有匹配的文档
curl ‘http://ip:port/index-name/_search?pretty’ -d{
“query”:{
“match_all”:{}
}
}
查询出所有的mappings
curl ‘http://ip:port/index-name/index-type/_mapping?pretty’
聚合过滤组合查询
先根据性别进行分组,然后组内在根据年龄进行分组,年龄组内在根据教育水平进行分组。
curl -XPOST 'http://ip/index-name/_search?pretty' -d '{
"aggs":{
"filtered":{
"aggs":{
"group_by_sex":{
"aggs":{
"group_by_age":{
"aggs":{
"group_by_education":{
"aggs":{
"distinct_phone":{
"cardinality":{"field":"phone.keyword"}
}
},
"terms":{
"field":"education.keyword",
"order":{"doc_count":"desc"},
"size":3
} }
},
"terms":{
"field":"age.keyword",
"order":{"doc_count":"desc"},
"size":3
}
}
},
"terms":{
"field":"sex.keyword",
"order":{"doc_count":"desc"},
"size":3
}
}
},
"filter":{
"bool":{
"must":[
{"bool":{
"should":{
"term":{"brand_id.keyword":"980"}
}
}
},
"bool":{
"should":{
"term":{"instr.keyword":"0"}
}
}
}
]
}
}
}
}
}'
terms里面的size是为了查询出排名前size的分组,如果查询出的分组数小于size,就显示查询出的分组数即可
must里面添加bool是为了组合should
should
如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
filter
必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
must里面的两个should条件必须同时满足,在同时满足的时候会增加文档评分,但是bool这些都在filter里面,filter是不评分模式。所以filter里面的查询就算增加评分也是没用的吧。
"must":[
{"bool":{
"should":{
"term":{"brand_id.keyword":"980"}
}
}
},
"bool":{
"should":{
"term":{"instr.keyword":"0"}
}
}
}
]
所以must里面的bool我觉得可以不用写的这么麻烦
"must":[
{"match":{"brand_id":"1"}},
{"match":{"prof":"工程师"}}
]
但是使用match,如果字段是analyzed(例如这里的是字符串)那么就会使用分析器,匹配的就不是精确值。
使用term精确匹配,不会使用分析器。将match改为term
"must":[
{"term":{"brand_id":"1"}},
{"term":{"prof":"工程师"}}
]
这里几次的小改动,但是查询结果都是相同的。
查询出来的结果:
查询结果前面的部分省了,主要解释一下后面的
不是我写的这个样例的查询结果
这个结果只是按照教育水平分的组,其他的条件和上面的一样
"aggregations":{
"filtered":{
"doc_count":3,//匹配的文档总数
"group_education":{//分组名
"doc_count_error_upper_bound":0,
"sum_other_count":0,//buckets中没有显示的文档数量
"buckets":[//分组信息,education指定的分组size是3但是这里只查出来两个分组,所以只显示这两个分组。
{
"key":"研究生",
"doc_count":2,
"distinct_phone":{
"value":0
}
},
{
"key":"本科",
"doc_count":1,
"distinct_phone":{
"value":0
}
}
]
}
}
}