查询相关
# match
查询和"我的宝马多少马力"这个查询语句匹配的文档
{"query":{"match":{"content":{"query":"我的宝马多少马力"}}}}
分析:上面的查询匹配就会进行分词,比如"宝马多少马力"会被分词为"宝马 多少 马力", 所有有关"宝马 多少 马力", 那么所有包含这三个词中的一个或多个的文档就会被搜索出来。
并且根据lucene的评分机制(TF/IDF)来进行评分
# match_phrase
想精确匹配所有同时包含"宝马 多少 马力"的文档怎么做?就要使用 match_phrase 了
{"query":{"match_phrase":{"content":{"query":"我的宝马多少马力"}}}}
分析:match_phrase查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含 全部 搜索词项,且 位置 与搜索词项相同的文档,且中间不许夹杂其他词。
本质上来讲,match_phrase 查询是利用一种低级别的 span 查询族(query family)去做词语位置敏感的匹配。 Span 查询是一种词项级别的查询,所以它们没有分词阶段;它们只对指定的词项进行精确搜索。
参考:https://www.elastic.co/guide/en/elasticsearch/guide/current/phrase-matching.html#phrase-matching
完全匹配可能比较严,我们会希望有个可调节因子,少匹配一个也满足,那就需要使用到slop。
{"query":{"match_phrase":{"content":{"query":"我的宝马多少马力","slop":1}}}}
分析:slop参数告诉match_phrase查询词条能够相隔多远时仍然将文档视为匹配。相隔多远的意思是,你需要移动一个词条多少次来让查询和文档匹配?
尽管在使用了slop的短语匹配中,所有的单词都需要出现,但是单词的出现顺序可以不同。如果slop的值足够大,那么单词的顺序可以是任意的。
参考:https://www.elastic.co/guide/en/elasticsearch/guide/current/slop.html
match和match_phrase的区别
match是全文搜索,也就是说这里的搜索条件是针对这个字段的全文,只要发现和搜索条件相关的Document,都会出现在最终的结果集中,事实上,ES会根据结果相关性评分来对结果集进行排序,这个相关性评分也就是我们看到的_score字段
match_phrase是短语搜索,亦即它会将给定的短语(phrase)当成一个完整的查询条件。当使用 match_phrase进行搜索的时候,你的结果集中,所有的Document都必须包含你指定的查询词组
# 相关性评分的相关知识
查询语句会为每个Document计算一个相关性评分_score,评分的计算方式取决于不同的查询类型。ES的相似度算法为TF/IDF(检索词频率/反向文档频率)
1)字段长度准则:这个准则很简单,字段内容的长度越长,相关性越低。
2)检索词频率准则:检索关键字出现频率越高,相关性也越高
3)反向Document频率准则:每个检索关键字在Index中出现的频率越高,相关性越低。
tips:
1)单个查询可以使用TF/IDF评分标准或其他方式。
2)如果多条查询子句被合并为一条复合查询语句,那么每个查询子句计算得出的评分会被合并到总的相关性评分中。
# multi_match
如果我们希望两个字段进行匹配,其中一个字段有这个文档就满足的话,使用multi_match
{"query":{"multi_match":{"query":"我的宝马多少马力","fields":["title","content"]}}}
分析:multi_match就涉及到匹配评分的问题了
1)我们希望完全匹配的文档占的评分比较高,使用best_fields
{
"query": {
"multi_match": {
"query": "我的宝马发动机多少",
"type": "best_fields",
"fields": [
"tag",
"content"
],
"tie_breaker": 0.3
}
}
}
分析:就是完全匹配"宝马 发动机"的文档评分会比较靠前,如果只匹配宝马的文档评分乘以0.3的系数
2)我们希望越多字段匹配的文档评分越高,使用most_fields
{
"query": {
"multi_match": {
"query": "我的宝马发动机多少",
"type": "most_fields",
"fields": [
"tag",
"content"
]
}
}
}
3)我们会希望这个词条的分词词汇是分配到不同字段中的,使用cross_fields
{
"query": {
"multi_match": {
"query": "我的宝马发动机多少",
"type": "cross_fields",
"fields": [
"tag",
"content"
]
}
}
}
# term
term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇
{"query":{"term":{"content":"汽车保养"}}}
分析:查出的所有文档都包含"汽车保养"这个词组的词汇。
使用term要确定的是这个字段是否“被分析”(analyzed),默认的字符串是被分析的
拿官网上的例子举例:
mapping是这样的:
PUT $index
{
"mappings": {
"my_type": {
"properties": {
"full_text": {
"type": "string"
},
"exact_value": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
PUT $index/_doc/1
{
"full_text": "Quick Foxes!",
"exact_value": "Quick Foxes!"
}
其中的full_text是被分析过的,所以full_text的索引中存的就是[quick, foxes],而extra_value中存的是[Quick Foxes!]。
# bool联合查询: must,should,must_not
如果我们想要请求"content中带宝马,但是tag中不带宝马"这样类似的需求,就需要用到bool联合查询。
联合查询就会使用到must,should,must_not三种关键词
must: 文档必须完全匹配条件
should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
must_not: 文档必须不匹配条件
比如上面那个需求:
{"query":{"bool":{"must":{"term":{"content":"宝马"}},"must_not":{"term":{"tags":"宝马"}}}}}
其他常用命令
添加这种权限请参考如下方法:
curl -u 超管用户:超管密码 -XPOST -H "Content-Type: application/json" '$ip:$port/_user/create' -d '
{
"username" : "username",
"password" : "passwd",
"ip_whitelist": ["*"],
"get_path" : ["/"],
"put_path" : [],
"post_path" : [],
"del_path" : [],
"head_path" : [],
"read_index": ["*"],
"write_index": []
}'
//线下创建索引
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index" -d '{"settings":{"index":{"number_of_shards":5,"number_of_replicas":1},"analysis":{"analyzer":{"comma":{"type":"pattern","pattern":","}}}}}'
//创建mapping
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index/_mapping/_doc?pretty" -d '{"properties":{"properties":{"id":{"type":"long"},"task_type":{"type":"keyword"},"task_info":{"type":"text","analyzer":"ik_max_word"},"t_score":{"type":"double"},"create_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},"tag":{"type":"text","analyzer":"comma"},"department_tag":{"type":"integer"}}}}'
//查看mapping
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_mapping?pretty"
//查看索引
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/_cat/indices?pretty"
http://10.157.41.8:8200/_cat/indices?v
//删除索引
curl -u $user:$password -H "Content-Type:application/json" -XDELETE "http://$ip:$port/$index
//查看别名
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/_alias/$index?pretty"
//集群状态
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/_cluster/health?pretty"
//索引详细
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/_cluster/health?level=indices"
//创建index
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index" -d '{"settings":{"index": {"number_of_shards":5, "number_of_replicas": 1}}}'
//设置_setting
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index" -d '{"settings":{"index": {"number_of_shards":5, "number_of_replicas": 1}}}'
//设置慢查询日志
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index/_settings" -d '{"index.indexing.slowlog":false}
'
//修改mappings_dynamic
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index/_mapping?pretty" -d '{"dynamic":"false"}'
//修改
curl -u $user:$password -H "Content-Type:application/json" -XPOST http://$ip:$port/$index/_doc/123456789/_update?pretty -d'{"doc":{"tag_filter":"头部标签,腰部标签"}}'
//条件查询
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_search" -d '{"query":{"bool":{"must":[{"term":{"status":1}}]}}}';
// ES新增字段
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index/_mapping?pretty" -d '{"properties":{"follower":{"type":"keyword"}}}'
//范围日期查询
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_search" -d '
{"query":{"bool":{"filter":{"bool":{"must":[{"range":{"publish_at":{"gte":"2022-06-03 00:00:00","lte":"2022-06-03 23:59:59"}}}]}}}},"from":0,"size":10}'
//条件修改
curl -u $user:$password -H "Content-Type:application/json" -XPOST "http://$ip:$port/$index/_doc/_update_by_query?conflicts=proceed" -d '{"script":{"inline":"ctx._source.follower=\"\";ctx._source.team=\"\""},"query":{"term":{"follower":"xxx"}}}'
//别名查询
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/_alias/$index?pretty
//ES增加或移除别名 add/remove
curl -u $user:$password -H "Content-Type:application/json" -XPOST "http://$ip:$port/_aliases" -d '
{
"actions" : [
{ "remove" : { "index" : $index,"alias" : "$index_write" } }
]
}'
// [FORBIDDEN/12/index read-only / allow delete (api)]
curl -u $user:$password -H "Content-Type:application/json" -XPUT "http://$ip:$port/$index/_settings/?pretty" -d'
{
"index": {
"blocks": {
"read_only_allow_delete": "false"
}
}
}'
//查看某个字段的分词情况
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_doc/1395212591265341440/_termvectors?fields=title&pretty"
//存在性查询-字段为空或不为空
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_doc/_search" -d '{"query":{"bool":{"must":[{"bool":{"must":[{"term":{"app_id":""}}]}},{"bool":{"must":[{"exists":{"field":"app_id"}}]}}]}}}'
//分组
curl -u $user:$password -H "Content-Type:application/json" -XGET "http://$ip:$port/$index/_search" -d '{"size":0,"aggs":{"field":{"terms":{"field":"tag"}}}}'
//脚本条件更新
curl -u user:pass -H "Content-Type:application/json" -XPOST "IP:PORT/index/type/_update_by_query?conflicts=proceed" -d '
{
"script":{
"inline":"ctx._source.$field_a=params.$param_a;ctx._source.$field_a=params.$param_b;",
"params":{
"$param_a":"val_a",
"$param_b":"val_b"
}
},
"query":{
"bool":{
"must":[
{
"term":{
"id":"123"
}
}
]
}
}
}'
//批量upsert更新
{"update":{"_id":"$id"}}
{"doc":{"$field":"$value"},"doc_as_upsert":true}