Elasticsearch 常用的增删改查语句
新增
PUT/index-name/type-name/id
{"json数据"}PUT/consultant_company_list_test1/_doc/1{"polar_abbreviation":"企查查","consultant_company_position":"北京市","consultant_company_admin_id":3,"channel_operation_id":"","good_at_industry_ids":"","is_cancel":0,"recommend_count":0,"consultant_company_name":"测试公司","industry":["金融","银行"]}// 新增的时候是不需要先创建索引的,创建数据的时候,如果索引不存在也会同时把索引创建了。// 但是这个时候默认创建出来的索引, mapping 是 ES 默认给设置的,有可能不合适,所以不建议用这种方式创建索引。// 如果对同一个index/type/id 使用 PUT,哪怕字段不一致,则后面的数据会覆盖前面的数据。// 创建成功后的返回结果说明:{"_index":"consultant_company_list_test1",// 创建的document所属的index"_type":"_doc",// 创建的document所属的type"_id":"1",// 创建的document的id"_version":1,// 创建的document的版本号"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}// 如果我们想要确保创建的 document 是新的,不会覆盖原来的 document PUT/consultant_company_list_test1/_doc/1/_create
{"polar_abbreviation":"企查查","consultant_company_position":"北京市","consultant_company_admin_id":3,"channel_operation_id":"","good_at_industry_ids":"","is_cancel":0,"recommend_count":0,"consultant_company_name":"测试公司","industry":["金融","银行"]}
删除
// 删除索引中的单条数据DELETE/index_one/product/1// 删除单个索引DELETE/index_one
// 删除多个索引DELETE/index_one,index_two
DELETE/index_*// 危险操作,删除全部索引DELETE/_all
DELETE/*
删除全部索引操作非常危险,禁止措施
elasticsearch.yml 做如下配置:
action.destructive_requires_name: true
修改
POST/ecommerce/product/1/_update
{"doc":{"name":"jiaqiangban gaolujie yagao"}}1. 修改的过程是 ES 获取某个文档中的所有字段,修改指定字段的内容,然后把老的 document 标记为deleted;
再重新创建一个新的document
2. update 内部会执行乐观锁的并发控制策略,每次更新时会更新版本号。
3. 如果遇到并发更新失败的时候,会有 retry(重试) 策略
(1)再次获取 document 数据和最新版本号;
(2)基于最新版本号再次去更新,如果成功那么就结束了;
如果失败,就重复 1 和 2 两个步骤,最多可以重复 retry_on_conflict 参数指定的次数
批量增删改
POST/_bulk
{"delete":{"_index":"test-index","_type":"test-type","_id":"1"}}{"create":{"_index":"test-index","_type":"test-type","_id":"2"}}{"test_field":"test2"}{"index":{"_index":"test-index","_type":"test-type","_id":"1"}}{"test_field":"test1"}{"update":{"_index":"test-index","_type":"test-type","_id":"3","_retry_on_conflict":"3"}}{"doc":{"test_field":"bulk filed 3"}}// 有哪些类型的操作可以执行呢?
(1)delete:删除一个文档,只要1个json串就可以了
(2)create:PUT/index/type/id/_create;只创建新文档
(3)index:普通的put操作,可以是创建文档,也可以是全量替换文档
(4)update:执行的partial update操作,即 post 更新
// bulk操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志// bulk size最佳大小: 如果太大的话,性能反而会下降; // 一般从1000~5000条数据开始,尝试逐渐增加。另外,如果看大小的话,最好是在5~15MB之间;
查询
查询指定索引下全部数据
GET/consultant_company_list_test1/_search
{"took":0,// 耗时"timed_out":false,// 是否超时"_shards":{"total":1,// 搜索了几个分片"successful":1,// 成功了几个"skipped":0,// 跳过了几个"failed":0// 失败了几个},"hits":{"total":{"value":1,// 查询到的数据的总量"relation":"eq"// 平常索引数据量不大的情况下这个数值没问题,// 但是当超出 10000 条数据的时候,// 这个 value 就固定为 10000。想要精确匹配数量,就需要通过 track-total-hits 参数来设置},"max_score":1,// 查询到的数据中匹配度分数最大值"hits":[// 查询到的结果{"_index":"consultant_company_list_test1","_type":"_doc","_id":"1","_score":1,// 匹配度分数"_source":{"polar_abbreviation":"企查查","consultant_company_position":"北京市","consultant_company_admin_id":3,"channel_operation_id":"","good_at_industry_ids":"","is_cancel":0,"recommend_count":0,"consultant_company_name":"测试公司"}}]}}"relation":"gte""relation":"eq"
gte 表示 total.value 是查询匹配总命中数的下限(大于等于)。eq 则表示 total.value 是准确计数。
查询指定索引下指定id的数据
GET/consultant_company_list_test1/_doc/1{"_index":"consultant_company_list_test1","_type":"_doc","_id":"1","_version":1,"_seq_no":0,"_primary_term":1,"found":true,// 查找成功为true,不成功为false"_source":{// 搜索到的数据"polar_abbreviation":"企查查","consultant_company_position":"北京市","consultant_company_admin_id":3,"channel_operation_id":"","good_at_industry_ids":"","is_cancel":0,"recommend_count":0,"consultant_company_name":"测试公司","industry":["金融","银行"]}}
查询指定索引下全部数据
// 查询指定索引下全部数据GET/consultant_company_list_test1/_doc/_search
{"query":{"match_all":{}}}
查询指定值(match)
// 查询指定值GET/consultant_company_list_test1/_doc/_search
{"query":{"match":{"consultant_company_name":"测试公司"}}}
在多个字段中查询指定值(multi_match)
GET/consultant_company_list_test1/_doc/_search
{"query":{"multi_match":{"query":"测试公司1","fields":["consultant_company_name","polar_abbreviation"]}}}
match、multi_match是模糊匹配,匹配时会对所查找的关键词进行分词,然后按分词匹配查找。
term 查询
GET/consultant_company_list_test1/_doc/_search
{"query":{"term":{"consultant_company_name":"测试公司"}}}
terms 查询
GET/consultant_company_list_test1/_doc/_search
{"query":{"terms":{"consultant_company_name":["测试公司1","测试公司2"]}}}
term、terms 会直接对关键词进行查找
范围查询
GET/consultant_company_list_test1/_doc/_search
{"query":{"range":{"price":{"gte":10,"lte":30}}}}
查询并排序
默认情况下,是按照_score降序排序的
GET/consultant_company_list_test1/_doc/_search
{"query":{"match":{"consultant_company_name":"测试公司1"}},"sort":{"id":{"order":"desc"}}}
分页查询
GET/consultant_company_list_test1/_doc/_search
{"query":{"match_all":{}},"from":0,// 从第几条数据开始"size":1// 查几条数据}
查询指定字段
GET/consultant_company_list_test1/_doc/_search
{"query":{"match_all":{}},"_source":["id","consultant_company_name"]}// 可以使用通配符*,显示要的字段、去除不需要的字段GET student/_search
{"query":{"match_all":{}},"_source":{"includes":"addr*","excludes":["name","bir*"]}}
全文检索
GET/consultant_company_list_test1/_doc/_search
{"query":{"match":{"producer":"测试公司 1"}}}
phrase search(短语搜索)
跟全文检索相相反,全文检索会将输入的搜索串拆解开来,去倒排索引里面去一一匹配,只要能匹配上任意一个拆解后的单词,就可以作为结果返回。phrase search,要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配,才能作为结果返回。
GET/consultant_company_list_test1/_doc/_search
{"query":{"match_phrase":{"producer":"测试公司 1"}}}
highlight search(高亮搜索结果)
GET/consultant_company_list_test1/_doc/_search
{"query":{"match":{"consultant_company_name":"测试公司"}},"highlight":{"fields":{"consultant_company_name":{}// 指定高亮的字段}}}
通配符查询
* 代表0个或多个字符
? 代表任意一个字符
GET/consultant_company_list_test1/_doc/_search
{"query":{"wildcard":{"consultant_company_name":"测试公司?"}}}
正则表达式查询
GET/consultant_company_list_test1/_doc/_search
{"query":{"regex":{"title":{"consultant_company_name":"测试公司[12]"}}}}
聚合搜索(很多种聚合方式,举几个例子)
term 分组统计
// 统计各个品牌的商品数量(只要分组就好了,自带统计数量)GET/goods/_search
{"aggs":{"brand_aggs":{"terms":{"field":"brand"}}}}// 统计各个品牌下的平均手机价格GET/goods/_search
{"size":0,"aggs":{"brand_aggs":{"terms":{"field":"brand"},"aggs":{"avg_price":{"avg":{// 还有其它聚合方式 sum,max,min"field":"price"}}}}}}// 统计各个品牌下的平均手机价格,并且按照平均价格降序排序GET/goods/_search
{"size":0,"aggs":{"brand_aggs":{"terms":{"field":"brand","order":{"avg_price":"desc"}},"aggs":{"avg_price":{"avg":{// 还有其它聚合方式 sum,max,min"field":"price"}}}}}}
histogram 分组统计
// 按照500为一个阶梯统计不同价位手机数量GET/goods/_search
{"size":0,"aggs":{"price_histogram":{"histogram":{"field":"price","interval":500// 间隔}}}}
range 分组统计
// 统计价格在4000-6000手机的数量GET/goods/_search
{"size":0,"aggs":{"price_range":{"range":{"field":"price","ranges":[{"from":4000,"to":6000}]}}}}// 统计价格在4000-6000手机的数量,然后在每组内再按照tag进行分组,最后再计算每组的平均价格GET/goods/_search
{"size":0,"aggs":{"price_range":{"range":{"field":"price","ranges":[{"from":4000,"to":6000}]},"aggs":{"group_by_tag":{"terms":{"field":"tags"},"aggs":{"avg_price":{"avg":{"field":"price"}}}}}}}}
日期分组统计
GET/cars/_search
{"size":0,"aggs":{"date":{"date_histogram":{// 需要聚合分组的字段名称, 类型需要为date, 格式没有要求"field":"sold",// 按什么时间段聚合, 这里是5分钟;分钟 (1m)、小时 (1h)、天 (1d)、星期 (1w)、月 (1M)、季度 (1q)、年 (1y)"interval":"5m",// 设置时区, 这样就相当于东八区的时间"time_zone":"+08:00",// 返回值格式化,HH大写,不然不能区分上午、下午"format":"yyyy-MM-dd HH",// 为空的话则填充0"min_doc_count":0,// 需要填充0的范围"extended_bounds":{"min":1533556800000,"max":1533806520000}}}}}
组合条件查询
bool:
must => 必须匹配 // 相当于MySQL的 and
must_not => 必须不匹配 // 相当于MySQL的 not
should => 应该匹配,既可以有,也可以没有 // 相当于MySQL的 or
filter => 过滤
// title必须包含elasticsearch,content可以包含elasticsearch也可以不包含,author_id必须不为111GET/website/article/_search
{"query":{"bool":{"must":[{"match":{"title":"elasticsearch"}}],"should":[{"match":{"content":"elasticsearch"}}],"must_not":[{"match":{"author_id":111}}]}}}SELECT product
FROM products
WHERE(price =20OR productID ="XHDK-A-1293-#fJ3")AND(price !=30)GET/my_store/products/_search
{"query":{"bool":{"should":[{"term":{"price":20}},{"term":{"productID":"XHDK-A-1293-#fJ3"}}],"must_not":{"term":{"price":30}}}}}
filter 与 query
1. 默认情况下,Elasticsearch 根据 相关性评分(relevance score) 对匹配到的搜索结果进行排序,
这个分数用来衡量每个文档与查询的匹配程度。
2. 相关性分数是一个正浮点数,在 search API 返回结果的 _score 元字段中。 _score越高,文档的相关性就越强。
3. 在 query 上下文中, 除了决定文档是否匹配之外,查询子句还计算文档的相关性得分(在元字段 _score 中显示)。
4. 在 filter 上下文中, 结果是简单的"是"或"否"--不会计算分数。
5. Elasticearch 会自动缓存经常使用的 filter,以提高性能。因此,filter速度要快于query
6. 一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;
如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter。
GET/_search
{"query":{"bool":{"must":[{"match":{"title":"Search"}},{"match":{"content":"Elasticsearch"}}],"filter":[{"term":{"status":"published"}},{"range":{"publish_date":{"gte":"2015-01-01"}}}]}}}
对上面的例子分析下:
query 参数表示整个语句是处于 query context 中
bool 和 match 语句被用在 query context 中,也就是说它们会计算每个文档的匹配度(_score)
filter 参数则表示这个子查询处于 filter context 中
filter 语句中的 term 和 range 语句用在 filter context 中,它们只起到过滤的作用,并不会计算文档的得分。
批量查询
// 查询不同index下的数据GET/_mget
{"docs":[{"_index":"test-index","_type":"test-type","_id":1},{"_index":"ecommerce","_type":"product","_id":2}]}// 查询的document是一个index下的不同typeGET/test_index/_mget
{"docs":[{"_type":"test_type","_id":1},{"_type":"test_type","_id":2}]}// 查询的数据都在同一个index下的同一个typeGET/ecommerce/product/_mget
{"ids":[1,2]}
scoll 滚动查询
scoll滚动查询就是,一批一批的查,直到所有数据都查询完处理完。
例如:如果一次性要查出来比如10万条数据,那么性能会很差,此时使用scoll滚动搜索,可以先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来。
scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的。
每次发送scroll请求,我们还需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了。
GET/test_index/test_type/_search?scroll=1m
{"query":{"match_all":{}},"sort":["_doc"],"size":3}// 搜索结果会有一个scoll_id,下一次再发送scoll请求的时候,必须带上这个scoll_id,这样才能接着查询下一批数据。{"_scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAACxeFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYBY0b25zVFlWWlRqR3ZJajlfc3BXejJ3AAAAAAAALF8WNG9uc1RZVlpUakd2SWo5X3NwV3oydwAAAAAAACxhFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYhY0b25zVFlWWlRqR3ZJajlfc3BXejJ3","took":5,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":10,"max_score":null,"hits":[{}]}}// 查询下一批数据GET/_search/scroll
{"scroll":"1m","scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAACxeFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYBY0b25zVFlWWlRqR3ZJajlfc3BXejJ3AAAAAAAALF8WNG9uc1RZVlpUakd2SWo5X3NwV3oydwAAAAAAACxhFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYhY0b25zVFlWWlRqR3ZJajlfc3BXejJ3"}
scroll + bulk 可以实现快速重建索引
multi-index 和 multi-type 搜索模式
GET/_search:所有索引,所有type下的所有数据都搜索出来
GET/index1/_search:指定一个index,搜索其下所有type的数据
GET/index1,index2/_search:同时搜索两个index下的数据
GET/*1,*2/_search:按照通配符去匹配多个索引
GET /index1/type1/_search:搜索一个index下指定的type的数据
GET /index1/type1,type2/_search:可以搜索一个index下多个type的数据
GET /index1,index2/type1,type2/_search:搜索多个index下的多个type的数据
GET /_all/type1,type2/_search:_all,可以搜索所有index下的指定type的数据
索引别名
索引别名可以指向一个或多个索引,并且可以在任何需要索引名称的API中使用。
索引别名允许我们执行以下操作:
1)索引重建时,可以把正在运行的索引和新的索引进行无缝切换,无需停机更新;
2)对多个索引进行分组组合(例如,last_three_months的索引别名:是过去3个月索引 logstash_201903, logstash_201904, logstash_201905的组合);
单个设置索引别名的方式
PUT/index1/_alias/index
一次设置多个索引别名的方式
POST/_aliases
{"actions":[{"add":{"index":"index1","alias":"index","is_write_index":true// 控制是否可以通过索引别名写入数据}},{"add":{"index":"index2","alias":"index"}}]}
删除别名
POST/_aliases
{"actions":[{"remove":{"index":"index2","alias":"index"}}]}
查询指定索引的别名
GET/index1/_alias
查询所有索引的别名
GET/_alias
假设没有别名,如何处理多索引检索?
GET/index1,index2/_search
有了别名后,多索引检索操作就变得简单了
1. 先为不同的索引设置相同的别名
POST/_aliases
{"actions":[{"add":{"index":"index1","alias":"index"}},{"add":{"index":"index2","alias":"index"}}]}2. 使用别名检索
GET/index/_search
校验查询语句是否合法
// 语法: GET /index/type/_validate/query?explain// 一般用在那种特别复杂庞大的搜索下,比如你一下子写了上百行的搜索,这个时候可以先用validate api去验证一下,语法是否合法GET/test_index/test_type/_validate/query?explain
{"query":{"math":{"test_field":"test"}}}
ES其它一些常用语句
查看索引
查看所有索引
GET/_cat/indices
查看某个索引的状态
GET/_cat/indices/index-name
查看某个索引的 mapping
GET/index-name/_mapping
查看、修改索引设置
GET index-name/_settings
PUT index-name/_settings
{"number_of_replicas":1}
开启、关闭索引
关闭一个索引(关闭索引后不能在读写 索引中的文档)POST index-name/_close
开启一个索引(将一个关闭的索引从新开启)POST index-name/_open
版权归原作者 @日月空@ 所有, 如有侵权,请联系我们删除。