1. 索引操作
1.1 创建索引
对比关系型数据库,创建索引就是创建数据库
创建索引:
在Postman中发PUT
请求:http://127.0.0.1:9200/index_name
例子:
响应:
{ "acknowledged": true, // 响应成功 "shards_acknowledged": true, "index": "shoping" }
1.2 获取索引信息
1. 获取指定索引信息:
在Postman中发GET
请求:http//127.0.0.1:9200/index_name
例子:
响应:
{ "shoping": { "aliases": {}, "mappings": {}, "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "1", "provided_name": "shoping", "creation_date": "1647768782140", "number_of_replicas": "1", "uuid": "AnHCrE-2SSG45KV5k_TNUQ", "version": { "created": "7150299" } } } } }
2. 获取所有索引信息:
在Postman中发GET
请求:http://127.0.0.1:9200/_cat/indices?v
- 参数v,详细显示信息
响应如下:
1.3 删除索引
在Postman中发DELETE
请求:http://127.0.0.1:9200/index_name
例子:
响应:
2. 文档操作
1.1 创建
ElasticSearch中的文档可以类比关系型数据库中的表数据,添加的数据格式为JSON格式。
在Postman中发起POST请求:http://127.0.0.1:9200/index_name/_doc
_doc并不指定,你创建文档的时候有可以_creat,过去之后仍然是_doc,因为在 ES 7.0 以后的版本 已经废弃文档类型Type了,一个 index 中只有一个默认的 type,即 _doc。
例子:
请求体内容:
{ "title":"小米手机", "category":"小米", "images":"http://xxx.com/xm.jpg", "price":3999.00 }
响应:
这里只可以发起POST请求,如果发起PUT请求,会响应报错:
指定ID:
上面方法创建成功后会返回一个唯一的ID(这个是es随机生成的)
你可以指定id,当你指定了id之后,ElasticSearch就不会再自动生成了
在Postman中发起POST请求:http://127.0.0.1:9200/index_name/_doc/id
例子:
响应:
{ "_index": "shopping", "_type": "_doc", "_id": "1001", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 1, "_primary_term": 1 }
1.2 查询
1.2.1主键查询
在Postman中发起GET
请求:http://127.0.0.1:9200/index_name/_doc/id
文档创建成功后会返回一个唯一的id(ElasticSearch随机生成的,也可以是你指定的)
例子:
1001是上面创建时指定的id。
响应:
{ "_index": "shopping", "_type": "_doc", "_id": "1001", "_version": 3, "_seq_no": 3, "_primary_term": 1, "found": true, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }
如果查询的文档id不存在:
响应:
{ "_index": "shopping", "_type": "_doc", "_id": "2001", "found": false }
1.2.2 全查询
查询所有index中所有文档:
在Postman中发起GET
请求:http://127.0.0.1:9200/index_name/_search
例子:
响应:
{ "took": 4, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 1.0, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 1.0, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1001", "_score": 1.0, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } } ] } }
1.2.3 条件查询
1.方法一:
在Postman中发起GET请求:http://127.0.0.1:9200/index_name/_search?q=param:value
但是在请求路径中添加额外的参数是比较麻烦的,而且这里的中文在请求路径中是容易出现乱码的,所以一般会调整为通过请求体来传递参数。
2.方法二(推荐):
在Postman中发起GET请求:http://127.0.0.1:9200/index_name/_search
请求体方式:
{ "query":{ // query:查询 "match":{ // match:全文检索匹配(1.2.9有详细讲) "field1":"value1" } } }
{ "query":{ // query:查询 "match_all":{ // match_all:全匹配 } } }
例子:
查询category字段为小米的文档
方法一查询:
方法二查询:
请求体:
{ "query":{ "match":{ "category":"小米" } } }
响应:
{ "took": 44, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 0.21072102, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 0.21072102, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1001", "_score": 0.21072102, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1002", "_score": 0.21072102, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1003", "_score": 0.21072102, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } } ] } }
1.2.4 分页查询
上述条件查询可以通过这样匹配到全部文档:
{ "query":{ // query:查询 "match_all":{ // match_all:全匹配 } } }
但是这样查询数量量太多了,而我们只需要一部分数据,怎么办,一般我们我们会采用分页查询,这个时候我们的请求体内容就需要修改:
在Postman中发起GET请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "query":{ // query:查询 "match_all":{ // match_all:全匹配 } }, "from": 0, // 起始页 "size": 1 // 每页文档数 }
例子
请求体:
{ "query":{ "match_all":{ } }, "from": 0, "size": 1 }
响应:
{ "took": 1, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 1.0, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 1.0, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } } ] } }
1.2.5 指定字段查询
但是感觉_source 里的字段有很多都是没啥用的,就可以通过指定字段来查询:
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "query":{ "match_all":{ } }, "from": 0, "size": 1, "_source":["field1","field2"] // 想要的字段 }
例子
只要文档的title字段
请求体:
{ "query":{ "match_all":{ } }, "from": 0, "size": 1, "_source":["title"] }
响应:
{ "took": 5, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 1.0, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 1.0, "_source": { "title": "小米手机" // 只有title字段 } } ] } }
1.2.6 查询排序
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "query":{ "match_all":{ } }, "sort":{ "field":{ "order":"desc" // desc:降序 || asc:升序 } } }
例子:
根据price价格进行升序排序:
请求体:
{ "query":{ "match_all":{ } }, "_source":["price"], "sort":{ "price":{ "order":"asc" } } }
响应:
{ "took": 3, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 6, "relation": "eq" }, "max_score": null, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "1004", "_score": null, "_source": { "price": 3000.0 }, "sort": [ 3000.0 ] }, { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": null, "_source": { "price": 3999.0 }, "sort": [ 3999.0 ] }, { "_index": "shopping", "_type": "_doc", "_id": "1001", "_score": null, "_source": { "price": 3999.0 }, "sort": [ 3999.0 ] }, { "_index": "shopping", "_type": "_doc", "_id": "1002", "_score": null, "_source": { "price": 3999.0 }, "sort": [ 3999.0 ] }, { "_index": "shopping", "_type": "_doc", "_id": "1003", "_score": null, "_source": { "price": 3999.0 }, "sort": [ 3999.0 ] }, { "_index": "shopping", "_type": "_doc", "_id": "1005", "_score": null, "_source": { "price": 20000.0 }, "sort": [ 20000.0 ] } ] } }
1.2.7 多条件查询
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
{ "query":{ "bool":{ // 多条件查询的话,需要参数bool "must":[// must:多个提交件必须同时成立 相当于and, should: 多条件不要求同时成立 相当于or { // 花括号中就是匹配规则,一个规则一对花括号 "match":{ "field1":"value1" } }, { "match":{ "field2":value2 } } ] } } }
例子
查询category为小米,且价格为3999.00 的文档:
请求体:
{ "query":{ "bool":{ // 多条件查询的话,需要参数bool "must":[// must:多个提交件必须同时成立 { // 花括号中就是匹配规则,一个规则一对花括号 "match":{ "category":"小米" } }, { "match":{ "price":3999.00 } } ] } } }
响应:
{ "took": 13, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": 1.1290771, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 1.1290771, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1001", "_score": 1.1290771, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1002", "_score": 1.1290771, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1003", "_score": 1.1290771, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } } ] } }
1.2.8 范围查询
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
注意:
这个范围是在你 多条件查询 后结果的基础上进一步查找
{ "query":{ "bool":{ "must":[ { "match":{ "field1":"value1" } }, { "match":{ "field2":value2 } } ], "filter":{ // 过滤 "range":{ // 范围 "field":{ "条件运算符": range // eg: gt:5000 大于5000的 } } } } } }
例子
查询华为手机或者苹果手机价格大于5000的文档:
请求体:
{ "query":{ "bool":{ "should":[ { "match":{ "category":"HuaWei" } }, { "match":{ "category":"Apple" } } ], "filter":{ // 过滤 "range":{ // 范围 "price":{ "gt": 5000 } } } } } }
响应
{ "took": 1, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 1.4417952, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "1001", "_score": 1.4417952, "_source": { "title": "苹果手机", "category": "Apple", "images": "http://xxx.com/xm.jpg", "price": 6599.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1006", "_score": 1.0630683, "_source": { "title": "华为手机", "category": "HuaWei", "images": "http://xxx.com/xm.jpg", "price": 44999.00 } } ] } }
1.2.9 全文检索
回到上面的条件查询,
{ "query":{ "match":{ "category":"米" } } }
上面这个条件仍然会匹配到category字段为小米的数据,这是因为:
当保存文档数据的时候,ElasticSearch会将数据文字进行分词、拆解操作,并将拆解后的数据保存到倒排索引中去,因此,即使只使用文字的一部分,仍然可以查询到数据,这种方式我们称之为全文检索,而且ElasticSearch对查询内容同样会进行分词,在倒排索引中进行匹配。
例子:
全文检索"小华"
http://127.0.0.1:9200/shopping/_search
请求体:
{ "query":{ "match":{ "title":"小华" } } }
响应:
{ "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 6, "relation": "eq" }, "max_score": 0.9444616, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "1005", "_score": 0.9444616, "_source": { "title": "华为手机", "category": "HuaWei", "images": "http://xxx.com/xm.jpg", "price": 5000.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1006", "_score": 0.9444616, "_source": { "title": "华为手机", "category": "HuaWei", "images": "http://xxx.com/xm.jpg", "price": 44999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1007", "_score": 0.9444616, "_source": { "title": "华为手机", "category": "HuaWei", "images": "http://xxx.com/xm.jpg", "price": 3645.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "TYu9pn8BfWqG58AR7Mzw", "_score": 0.9444616, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1004", "_score": 0.9444616, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3000.00 } }, { "_index": "shopping", "_type": "_doc", "_id": "1003", "_score": 0.9444616, "_source": { "title": "小米手机", "category": "小米", "images": "http://xxx.com/xm.jpg", "price": 3999.00 } } ] } }
小结:
可以看到 你查询的条件是"title":"小华"
,但是却查询到了小米和华为,这就是因为ES对查询内容进行了分词,分成了小
、华
对倒排索引进行了匹配,从而匹配到了小米和华为。
1.2.10 完全匹配
由1.2.9
全文检索可以看出,你在1.2.3
条件匹配的方式并不是完全匹配的。
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "query":{ "match_phrase":{ // 完全匹配 "field":"value" } } }
例子:
http://127.0.0.1:9200/shopping/_search
请求体:
{ "query":{ "match_phrase":{ // 完全匹配 "title":"小华" } } }
响应:
{ "took": 9, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 0, "relation": "eq" }, "max_score": null, "hits": [] } }
1.2.11 高亮查询
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "query":{ "match_phrase":{ // 完全匹配 "field":"value" } }, "highlight":{ "fields":{ "title":{} } } }
例子:
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/shopping/_search
请求体:
{ "query":{ "match_phrase":{ // 完全匹配 "title":"华为手机" } }, "highlight":{ // 高亮显示 "fields":{ "title":{} } } }
响应:
{ "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 3, "relation": "eq" }, "max_score": 2.00324, "hits": [ { "_index": "shopping", "_type": "_doc", "_id": "1005", "_score": 2.00324, "_source": { "title": "华为手机", "category": "HuaWei", "images": "http://xxx.com/xm.jpg", "price": 5000.00 }, "highlight": { "title": [ "<em>华</em><em>为</em><em>手</em><em>机</em>" // 高亮显示 ] } } ] } }
1.2.12 聚合查询
如果想查询结果进行分组或者统计分析,就使用聚合查询:
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/index_name/_search
请求体:
{ "aggs":{ // 聚合操作 "group_name": { // 聚合结果的名字,随意起名 "terms":{ // 分组 "field":"field1" // 分组字段 } } } }
例子-分组:
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/shopping/_search
请求体:
{ "aggs":{ // 聚合操作 "price_group": { // 聚合结果的名字,随意起名 "terms":{ // 分组 || terms:分组; avg:平均值 "field":"price" // 分组字段 } } }, "size":0 // 舍弃原始数据 }
响应:
{ "took": 6, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 8, "relation": "eq" }, "max_score": null, "hits": [] // 原始数据 }, "aggregations": { "price_group": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": 3999.0, "doc_count": 2 }, { "key": 3000.0, "doc_count": 1 }, { "key": 3645.0, "doc_count": 1 }, { "key": 4555.0, "doc_count": 1 }, { "key": 5000.0, "doc_count": 1 }, { "key": 6599.0, "doc_count": 1 }, { "key": 44999.0, "doc_count": 1 } ] } } }
例子-平均值
在Postman中发起GET
请求,携带请求体:http://127.0.0.1:9200/shopping/_search
请求体:
{ "aggs":{ // 聚合操作 "price_avg": { // 聚合结果的名字,随意起名 "avg":{ // 平均值 "field":"price" // 分组字段 } } }, "size":0 // 舍弃 }
响应:
{ "took": 4, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 8, "relation": "eq" }, "max_score": null, "hits": [] // 原始数据 }, "aggregations": { "price_avg": { "value": 9474.5 // 平均值 } } }