Elasticsearch
是面向文档型数据库,一条数据在这里就是一个文档。
关系型数据库MySQL存储数据的概念与Elasticsearch里存储文档数据的对比:
Elasticsearch里的Index
可以看作一个库,而Type
相当于表,Documents
则相当于表的行。Fields
则相当于表的列。
在新版Elasticsearch中,Type
的概念已经被逐渐弱化。Elasticsearch 6.X中,一个index下已经只能包含一个type
对比关系型数据库,创建索引就等同于创建数据库。
只需向ES服务器发PUT
请求:
# http://<ES服务地址>/<索引名称>
curl -X PUT http://localhost:9200/supermarket
# 返回值:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "supermarket"
}
只需向ES服务器发GET
请求:
# http://<ES服务地址>/<索引名称>
curl http://localhost:9200/supermarket
# 返回值:
{
"supermarket": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1660186748982",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "jlllGg_3TRmLKtC8r_ZDoA",
"version": {
"created": "7080199"
},
"provided_name": "supermarket"
}
}
}
}
# http://<ES服务器地址>/_cat/indices?v
curl http://localhost:9200/_cat/indices?v
返回值:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open supermarket jlllGg_3TRmLKtC8r_ZDoA 1 1 0 0 208b 208b
yellow open bookstore 6r4T-ng1Qeufs4jJpJPahw 1 1 1 0 4.4kb 4.4kb
yellow open shopping 2_vlSiDmRYuOG6eLRudKOg 1 1 0 0 208b 208b
只需向ES服务器发DELETE
请求:
# http://<ES服务地址>/<索引名称>
curl -X DELETE http://localhost:9200/supermarket
返回值:
{
"acknowledged":true
}
这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为JSON格式
只需向ES服务器发送POST
请求:
# POST http://<ES服务地址>/<索引名称>/_doc
# On Windows, escape the double quotes
curl -H "Content-Type: application/json" -X POST -d {\"title\":\"AppleWatch6\",\"category\":\"Apple\",\"price\":3999.00} http://localhost:9200/supermarket/_doc
# For *nix or Mac OSX, add a single quote
curl -H "Content-Type: application/json" -X POST -d '{"title":"AppleWatch6","category":"Apple","price":3999.00}' http://localhost:9200/supermarket/_doc
返回结果:
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
这种方式发送请求不是幂等性的,每次都会返回不一样的随机ID,代表生成了多条同样的数据。如果想指定返回ID可以用下面的请求:
# POST http://<ES服务器地址>/<索引名称>/_doc/<id>
curl -H "Content-Type: application/json" -X POST -d {\"title\":\"AppleWatch6\",\"category\":\"Apple\",\"price\":3999.00} http://localhost:9200/supermarket/_doc/1001/
返回结果:
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1001",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
如果要生成指定ID的数据时,就是幂等性操作,遂也可以使用PUT方法来进行新建文档。
# PUT http://<ES服务器地址>/<索引名称>/_doc/<id>
curl -H "Content-Type: application/json" -X PUT -d {\"title\":\"AppleWatch6\",\"category\":\"Apple\",\"price\":3999.00} http://localhost:9200/supermarket/_doc/1001/
返回结果:
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1003",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}
同时还可以用/_create来新建指定ID的数据
# PUT http://<ES服务器地址>/<索引名称>/_create/<id>
curl -H "Content-Type: application/json" -X PUT -d {\"title\":\"AppleWatch6\",\"category\":\"Apple\",\"price\":3999.00} http://localhost:9200/supermarket/_create/1001/
# POST http://<ES服务器地址>/<索引名称>/_create/<id>
curl -H "Content-Type: application/json" -X POST -d {\"title\":\"AppleWatch6\",\"category\":\"Apple\",\"price\":3999.00} http://localhost:9200/supermarket/_create/1001/
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1005",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 6,
"_primary_term": 1
}
查询指定文档
# GET http://<ES服务器地址>/<索引名称>/_doc/<id>
curl -X GET http://localhost:9200/supermarket/_doc/1001
返回结果:
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1002",
"_version": 1,
"_seq_no": 2,
"_primary_term": 1,
"found": true,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
}
查询所有文档
# GET http://<ES服务器地址>/<索引名称>/_search
curl -X GET http://localhost:9200/supermarket/_search
返回结果:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 8,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1002",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
}
]
}
}
全量数据更新
# PUT http://<ES服务器地址>/<索引名>/_doc/<id>
curl -X PUT -H "Content-Type: application/json" -d {\"title\":\"xiaomi10Ultra\",\"category\":\"xiaomi\",\"price\":3999.00} http://localhost:9200/supermarket/_doc/1002
返回结果:
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1002",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 9,
"_primary_term": 1
}
局部数据更新
# POST http://<ES服务器地址>/<索引名>/_update/<id>
curl -X POST -H "Content-Type: application/json" -d {\"doc\": {\"title\":\"HUWAWEI\"}} http://localhost:9200/supermarket/_update/1002
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1002",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 10,
"_primary_term": 1
}
# DELETE http://<ES服务器地址>/<索引名>/_doc/<id>
curl -X DELETE http://localhost:9200/supermarket/_doc/1002
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1002",
"_version": 1,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 13,
"_primary_term": 1
}
根据请求路径进行条件查询
# GET http://<ES服务器地址>/<索引名>/_search?q=<字段名>:<字段值>
curl http://localhost:9200/supermarket/_search?q=category:小米
返回结果:
{
"took": 37,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 2.9855614,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 2.9855614,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
}
}
]
}
}
但请求参数放在请求路径中时,如果查询条件是中文,在不同的操作环境会产生乱码的情况导致无法查询出有效数据。
放在请求体里便可解决这个问题:
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match": {
"category": "Apple"
}
}
}
curl -X GET -H "Content-Type: application/json" -d {\"query\":{\"match\":{\"category\":\"Apple\"}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 16,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.15226628,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 0.15226628,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
}
]
}
}
还可以通过发送请求体的方式查询所有数据:
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match_all": {}
}
}
curl -X GET -H "Content-Type: application/json" -d {\"query\":{\"match_all\":{}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 1.0,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
}
}
]
}
}
from:代表从第几条数据开始
size:代表每页显示多少条数据
做翻页的通用格式为:(页码-1)*每页数据
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5
}
curl -X GET -H "Content-Type: application/json" -d {\"query\":{\"match_all\":{}},\"from\":0,\"size\":5} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "1003",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
}
]
}
}
_source: 查询指定字段列表
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match_all": {}
},
"_source": ["title"]
}
curl -X GET -H "Content-Type:application/json" -d {\"query\":{\"match_all\":{}},\"_source\":[\"title\"]} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 1.0,
"_source": {
"title": "Apple Watch 6"
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 1.0,
"_source": {
"title": "xiaomi 10 Ultra"
}
}
]
}
}
sort:{”字段名”: {”order”: “desc/asc”}}
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match_all": {}
},
"sort": {
"price": {
"order": "desc"
}
}
}
curl -X GET -H "Content-Type:application/json" -d {\"query\":{\"match_all\":{}},\"sort\":{\"price\":{\"order\":\"desc\"}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": null,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
},
"sort": [
3999.0
]
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": null,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
},
"sort": [
3999.0
]
}
]
}
}
must:所有条件必须同时满足才能执行查询,相当于and
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"bool": {
"must": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"price": 3999
}
}
]
}
}
}
curl -H "Content-Type:application/json" -d {\"query\":{\"bool\":{\"must\":[{\"match\":{\"category\":\"小米\"}},{\"match\":{\"price\":3999}}]}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 3.9855614,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 3.9855614,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
}
}
]
}
}
should:所有条件只需满足指定一个即可执行查询,相当于or
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"match_all": {}
},
"sort": {
"price": {
"order": "desc"
}
}
}
curl -H "Content-Type:application/json" -d {\"query\":{\"bool\":{\"should\":[{\"match\":{\"category\":\"Apple\"}},{\"match\":{\"category\":\"小米\"}}]}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 2.9855614,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 2.9855614,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 0.15226628,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
}
]
}
}
lt:小于
lte:小于等于
gt:大于
gte:大于等于
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体:
{
"query": {
"bool": {
"filter": {
"range": {
"price": {
"lt": 3999
}
}
}
}
}
}
curl -H "Content-Type:application/json" -d {\"query\":{\"bool\":{\"filter\":{\"range\":{\"price\":{\"lt\":3999}}}}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.0,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "sUNui4IBGBS9mFAECUdX",
"_score": 0.0,
"_source": {
"title": "Apple Watch 6",
"category": "Apple",
"price": 3999.00
}
},
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 0.0,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
}
}
]
}
}
# GET http://<ES服务器地址>/<索引名>/_search
# 请求体
{
"query": {
"bool": {
"must": [
{
"match": {
"category": "小"
}
}
]
}
},
"highlight": {
"fields": {
"category": {}
}
}
}
curl -H "Content-Type:application/json" -d {\"query\":{\"match\":{\"category\":\"小\"}},\"highlight\":{\"fields\":{\"category\":{}}}} http://localhost:9200/supermarket/_search
返回结果:
{
"took": 73,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.4927807,
"hits": [
{
"_index": "supermarket",
"_type": "_doc",
"_id": "skNvi4IBGBS9mFAECkfu",
"_score": 1.4927807,
"_source": {
"title": "xiaomi 10 Ultra",
"category": "小米",
"price": 3999.00
},
"highlight": {
"category": [
"<em>小</em>米"
]
}
}
]
}
}
elasticsearch插入数据时会默认把数据分词后添加到倒排索引内一份。比如说存进一条中文数据“你好”,es会分别把“你”和“好”维护到倒排索引内。这时进行全文检索时,无论是单查“你”还是“好”都会把“你好”匹配出来。
match默认会对匹配的数据进行全文检索,match_phrase会对匹配的数据进行完全匹配检索。
基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建