1.集群
cluster通过cluster.name构建,选举一个master,管理集群级别的变化,例如索引的创建删除、节点的加入移除等,不参与文档级别的变化和查询。
2.集群健康
GET /_cluster/health
green
All primary and replica shards are active.
yellow
All primary shards are active, but not all replica shards are active.
red
Not all primary shards are active.
3.分片
一个索引实际上是一个逻辑命名空间和几个物理分片。一个文档只属于一个主分片,一个索引有多个分片(主、复制)。一个索引拥有几个主分片决定了一个索引可以存储的文档大小。一个主分片可以包含 Integer.MAX_VALUE - 128个文档。
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}设置blog索引拥有三个主分片,每个主分片拥有一个复制分片,单台运行Es时,因为没有别的节点分配给复制分片,所以节点为yellow,表示没有激活的复制分片。
索引使用中,主分片数量不可改,复制分片可以改。
4.document metadata
_index 类似关系数据库中数据库的概念,命名必须小写,不能以"_"开头,不能包含",".
_type 类似关系数据库中表的概念,命名不能以数字和"_"开头,不能包含",",长度限制在256个字符。
_id 文档的唯一标识符,字符串类型,可以自己指定,也可以由elasticsearch生成。
5.文档版本
当文档发生变化时,文档版本也发生变化,同时把新文档同步到其他复制节点,由于网络不确定性,多次修改同时到达,会发生冲突,本分节点会选择最新版本文档,忽略老文档。
并发控制冲突的两种解决方案:
Pessimistic concurrency control:传统数据库的做法,在行上加锁。
Optimistic concurrency control:Es使用的,在读写之间如果数据出现变化,则更新失败。
所以Es的更新操作很可能失败,提供了retry_on_conflict=5参数可以重试次数。貌似默认重试三次。
6.bulk
使用时注意大小,最好在1000-5000个文档之间,当然一千个1K的文档和一千个1M的文档还以不一样的,所以,bulk大小最好在5M-15M之间。
7.分片路由
当索引一个文档时,需要文档应该属于哪个分片。使用下面的公式计算,routing是文档的id。这也解释了,number_of_primary_shards只能在索引创建时设置,不能更改;如果修改了,之前索引的数据就失效了,找不到了。
shard = hash(routing) % number_of_primary_shards
8.timeout
当设置查询超时时,es会在即将超时,不待所有分片处理结束就返回数据关闭连接,但是,查询处理还在继续。所以此参数不能避免长时间的查询。
9._all field
当索引一个文档时,会生成一个连接所有字符串field的 _all field,对于不指定field的查询很有用。
10.More Complicated Queries
The next query searches for tweets, using the following criteria:
• The name field contains mary or john
• The date is greater than 2014-09-10
• The _all field contains either of the words aggregations or geo
+name:(mary john) +date:>2014-09-10 +(aggregations geo)
?q=%2Bname%3A(mary+john)+%2Bdate%3A%3E2014-09-10+%2B(aggregations+geo)
11.filter
filter被移除了,现在和,must\must-not\should同级,包含在bool里,例如:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2014-01-01" }}},
{ "range": { "price": { "lte": 29.99 }}}
],
"must_not": [
{ "term": { "category": "ebooks" }}
]
}
}
}
}
当查询只有filter时,所有匹配的文件_score为0,可以使用constant_score ,此时所有匹配项_score为1。两种方式排序都是随机的。
{
"constant_score": {
"filter": {
"term": { "category": "ebooks" }
}
}
}
12.关于match和term
使用match时,如果field是分词字段,则先对query string使用字段分词器分词,让使用分词后的terms查询。
如果field没有使用分词,则不分词,使用绝对匹配。
原文:
If you run a match query against a full-text field, it will analyze the query string by using the correct analyzer for that field before executing the search。
If you use it on a field containing an exact value, such as a number, a date, a Boolean, or a not_analyzed string field, then it will search for that exact value。
13.must\must-not\should
14.validating queries
类似mysql的explain,使用validate-query API验证查询是否合法,例:
GET /gb/tweet/_validate/query
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
加上explain可以查看详细的错误信息,成功后可以返回查询是如何执行的,例:
GET /_validate/query?explain
{
"query": {
"match" : {
"tweet" : "really powerful"
}
}
}
15.sort
默认使用_score排序,当_score为空时,随机返回。可以使用sort指定排序字段,可以指定多个field;当field为多值时,可以使用min, max, avg, or sum 指定排序模式。例:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
16.multifield
个人理解,当我们需要一个field分词数据和不分词数据同时存在时,如果定义两个field,就太浪费了。ES提供了multifield将一个field映射,解决这个问题。例:
"tweet": {
"type": "string",
"analyzer": "english",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
},
"sort": "tweet.raw"
}
存储时,只需要设置tweet的值就可以使用tweet.raw。
不知道能否映射为不同类型,可以试验一下?
17.explain
类似mysql中的explain,可以显示每个匹配文档相关度如何计算,例:
GET /_search?explain
{
"query" : { "match" : { "tweet" : "honeymoon" }}
}
也可以用来理解一个文档为何被匹配或不被匹配,例:
GET /us/tweet/12/_explain
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 2 }},
"must" : { "match" : { "tweet" : "honeymoon" }}
}
}
}
18.索引操作
禁止自动创建索引 : action.auto_create_index: false
禁止模糊匹配或_all删除索引: action.destructive_requires_name: true
19.analyzer
分词器将三块功能包装到一起:
Character filters:被用来整理字符串,例如文本中含有HTML代码如<p><div>,可以用 html_strip character 移除并转换成Unicode编码。
Tokenizers:文本分割器,一个analyer必须有一个且仅有一个文本分词器,用来把文本分割成术语和符号。
Token filters:文本分割结束后,对分割的后的标记处理,例如过滤停止词、把所有单词转成小写、添加同义词等。
20.索引管理
dynamic mapping:es遇到新的field时,会自动添加到映射。你可通过dynamic配置,控制这一行为;
true :Add new fields dynamically—the default
false :Ignore new fields (依旧会存储_source,但是不能查询)
strict :Throw an exception if an unknown field is encountered
实例:
PUT /my_index
{
"mappings": {
"my_type": {
"dynamic": "strict",
"properties": {
"title": { "type": "string"},
"stash": {
"type": "object",
"dynamic": true
}
}
}
}
}
21._source和_all
文档json压缩存储,可以设置是否存储。
暂时不知道对于查询有何影响,待深入了解测试?
PUT /my_index
{
"mappings": {
"my_type": {
"_source": {
"enabled": false
}
}
}
}
GET /_search
{
"match": {
"_all": "john smith marketing"
}
}
_all设置使用"my_type": { "_all": { "enabled": false }}:则不再有被_all查询到的field,也可以使用"include_in_all"配置field的默认设置,例如:
PUT /my_index/my_type/_mapping
{
"my_type": {
"include_in_all": false,
"properties": {
"title": {
"type": "string",
"include_in_all": true
},
...
}
}
}
使用_default_配置默认设置
22.match
"match": {
"title": {
"query": "BROWN DOG!",
"operator": "and"
}
}
"match": {
"title": {
"query": "quick brown dog",
"minimum_should_match": "75%"
}
}
23.best_fields, most_fields, and cross_fields
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Brown fox" }},
{ "match": { "body": "Brown fox" }}
]
}
}
计算文档分数时,取field分数最高的值作为文档分数。
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
],
"tie_breaker": 0.3
}
计算best-field分数,然后计算每个匹配项的分数,加在一起作为文档分数。tie_breake最好在0.1-0.4之间,这样才不会覆盖dis_max.
best_fields:
{
"multi_match": {
"query": "Quick brown fox",
"type": "best_fields",
"fields": [ "title", "body" ],
"tie_breaker": 0.3,
"minimum_should_match": "30%"
}
}
most_fields:
"query": {
"multi_match": {
"query": "jumping rabbits",
"type": "most_fields",
"fields": [ "title^10", "title.std" ]
}
}
24.match_phrase
对短语匹配有顺序,例如“quick fox”要求文档必须含有quick和fox两个词,且两个词位置间隔为1.
可以配置
slop对两个词的位置滑动
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": {
"query": "quick fox",
"slop": 1
}
}
}
{
"query": {
"match_phrase": {
"title": {
"query": "quick fox",
"slop": 1
}
}
}
}
针对数组类型,分词后的词序是将数组拼接后的分词词序,为了将每个数组元素的位置分开可以使用
position_increment_gap配置
PUT /my_index/_mapping/groups
{
"properties": {
"names": {
"type": "string",
"position_increment_gap": 100
}
}
{
"properties": {
"names": {
"type": "string",
"position_increment_gap": 100
}
}
}
使用slop时,匹配到的文档词距越近分数越高。
25.rescore
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "30%"
}
}
},
"rescore": {
"window_size": 50,
"query": {
"rescore_query": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 50
}
}
}
}
}
{
"query": {
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "30%"
}
}
},
"rescore": {
"window_size": 50,
"query": {
"rescore_query": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 50
}
}
}
}
}
}
26.must-not的弊端
当我们查询Apple时,希望查询到的的是一家公司而不是水果,我们可以这样做:
GET /_search
{
"query": {
"bool": {
"must": {
"match": {
"text": "apple"
}
},
"must_not": {
"match": {
"text": "pie tart fruit crumble tree"
}
}
}
}
}
但是这种做法太严格了,会丢失相关性很强的包含tree的文档。类似的场景可以做如下改动:
GET /_search
{
"query": {
"boosting": {
"positive": {
"match": {
"text": "apple"
}
},
"negative": {
"match": {
"text": "pie tart fruit crumble tree"
}
},
"negative_boost": 0.5
}
}
}
27.几种控制_score的方法boost方法
function_score配合field_value_factor,new_score = old_score * number_of_votes
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes"
}
}
}
}
使用modifier,new_score = old_score * log(1 + number_of_votes)
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p"
}
}
}
}
使用factor,new_score = old_score * log(1 + factor * number_of_votes)
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p",
"factor": 2
}
}
}
}
使用 boost_mode,控制_scoreh和function_score的处理方式,取值multiply、sum、min、max、replace
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum"
}
}
}
max_boost控制function_score的最大值,不是控制最终的_score值
GET /blogposts/post/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum",
"max_boost": 1.5
}
}
}