ElasticSearch与传统关系型数据库对比
在ES中每条记录就是一个Document对象
基础命令:
创建索引(创建索引相当于创建数据库)
PUT /shopping
根据索引名称 获取索引信息
GET /shopping
获取所有索引信息
GET /_cat/indices?v # 说明:参数v表示获取详细信息
根据索引名称 删除索引
DELETE /shopping
创建文档(即为索引写入一条记录)
POST /shopping/_doc # 说明:_doc代表添加一条文档记录
{
"name":"zs",
"age":18,
"address":"四川省"
}
响应:
_id字段为ES自动生成的这条记录的唯一标识,相当于数据库的主键
{
"_index" : "shopping",
"_id" : "H_HxSosBy1IIAtuiyzK2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 2
}
我们可以通过响应的_id去查询记录,但由于ES随机生成的ID不好记,所以我们可以在写入记录时手动指定id(在_doc后面跟上自定义ID)
POST /shopping/_doc/1001
{
"name":"ls",
"age":26,
"address":"重庆市"
}
响应:
{
"_index" : "shopping",
"_id" : "1001",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 2
}
根据主键查询文档记录
# 查询主键为1001的数据
GET /shopping/_doc/1001
查询索引下面的所有记录
GET /shopping/_search
更新记录
# 全量更新(覆盖)[使用PUT请求,PUT具有幂等性]
PUT /shopping/_doc/1001
{
"name":"ls02",
"age":26,
"address":"重庆市"
}
# 局部更新[使用POST请求,POST不具有幂等性]
POST /shopping/_update/1001
{
"doc":{ # doc中传入局部更新的字段及值
"name":"ls03"
}
}
删除记录
DELETE /shopping/_doc/1001
单条件查询&取指定字段&排序&分页(单条件使用match)
# 单条件查询&取指定字段&排序&分页
GET /shopping/_search
{
"query": { # query代表查询
"match": { # match代表匹配查询,类似于Where
"category": "小米"
}
},
"_source": ["title","price"], # _source代表要展示哪些字段
"sort": [ # sort代表排序
{
"price": { # 根据"price"字段排序
"order": "desc" # order 用于指定排序规则(升序/降序)
}
}
],
"from": 0, # from代表分页的页码(计算规则同SQL Limit的计算规则一样)
"size": 2 # size代表每页取多少条
}
# 查询索引下所有数据写法也可如下
GET /shopping/_search
{
"query": {
"match_all": {
}
}
}
多条件查询&范围查询(多条件使用bool)
# 多条件(AND-且)同时成立(查询category(品牌)为小米,且price为3200的商品)
GET /shopping/_search
{
"query": { # 查询
"bool": { # 多条件使用bool
"must": [ # 多条件同时成立用must
{
"match": { # 每个match用于匹配一个条件
"category": "小米"
}
},
{
"match": { # 每个match用于匹配一个条件
"price": 3200
}
}
]
}
}
}
多条件(OR-或)同时成立(查询category(品牌)为小米或华为且价格大于3000的商品)
GET /shopping/_search
{
"query": {
"bool": { # 多条件查询使用bool
"should": [ # 多条件 "OR-或"使用should表示
{
"match": { # 每个match用于匹配一个条件
"category": "小米"
}
},
{
"match": { # 每个match用于匹配一个条件
"category": "华为"
}
}
],
"filter": [ # 过滤
{
"range": { # 范围过滤使用range
"price": {
"gte": 3000 # 过滤price(价格)字段。取price大于等于3000的商品
}
}
}
]
}
}
}
全文检索&完全匹配&高亮查询
# 全文检索的含义是将你match中的字符串进行分词再去索引库中匹配对应的记录
例一:全文检索 + 高亮
GET /shopping/_search
{
"query": {
"match": { # match会进行全文检索
"category": "小华"
}
},
"highlight": { # highlight代表高亮
"fields": { # fields中指定高亮的字段
"category": {} # 高亮字段为“category”
}
}
}
# 响应:因为全文检索是先分词再去匹配,所以其查询出来的数据会把category含有“小”或“华”的数据都匹配出来
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.3862942,
"hits" : [
{
"_index" : "shopping",
"_id" : "1003",
"_score" : 1.3862942,
"_source" : {
"title" : "华为手机",
"category" : "华为",
"price" : 4200
},
"highlight" : {
"category" : [
"<em>华</em>为"
]
}
},
{
"_index" : "shopping",
"_id" : "1001",
"_score" : 0.2876821,
"_source" : {
"title" : "小米手机",
"category" : "小米",
"price" : 3200
},
"highlight" : {
"category" : [
"<em>小</em>米"
]
}
},
{
"_index" : "shopping",
"_id" : "1002",
"_score" : 0.2876821,
"_source" : {
"title" : "红米手机",
"category" : "小米",
"price" : 2200
},
"highlight" : {
"category" : [
"<em>小</em>米"
]
}
}
]
}
}
例二:完全匹配 + 高亮
# 完全匹配则是对于输入的匹配词不进行分词进行完全匹配,如上匹配词为"小华",进行完全匹配是没有记录的
GET /shopping/_search
{
"query": {
"match_phrase": { # match_phrase会进行完全匹配
"category": "小华" # 完全匹配的字段为category,值为“小华”
}
},
"highlight": { # 指定高亮字段
"fields": {
"category": {}
}
}
}
# 响应
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
例三:完全匹配 + 高亮
# 使用完全匹配去匹配category字段为“小米”,并且高亮category字段中匹配到的“小米”字符串
GET /shopping/_search
{
"query": {
"match_phrase": { # match_phrase表示完全匹配
"category": "小米"
}
},
"highlight": {
"fields": {
"category": {}
}
}
}
# 响应
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "shopping",
"_id" : "1001",
"_score" : 0.5753642,
"_source" : {
"title" : "小米手机",
"category" : "小米",
"price" : 3200
},
"highlight" : {
"category" : [
"<em>小</em><em>米</em>"
]
}
},
{
"_index" : "shopping",
"_id" : "1002",
"_score" : 0.5753642,
"_source" : {
"title" : "红米手机",
"category" : "小米",
"price" : 2200
},
"highlight" : {
"category" : [
"<em>小</em><em>米</em>"
]
}
}
]
}
}
聚合查询
# 例一:根据price字段聚合(取原始数据 + 聚合数据)
GET /shopping/_search
{
"aggs": {
"price_group": { # 自定义聚合名称
"terms": {
"field": "price"
}
}
}
}
响应:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [ # 原始数据
{
"_index" : "shopping",
"_id" : "1001",
"_score" : 1.0,
"_source" : {
"title" : "小米手机",
"category" : "小米",
"price" : 3200
}
},
{
"_index" : "shopping",
"_id" : "1002",
"_score" : 1.0,
"_source" : {
"title" : "红米手机",
"category" : "小米",
"price" : 2200
}
},
{
"_index" : "shopping",
"_id" : "1003",
"_score" : 1.0,
"_source" : {
"title" : "华为手机",
"category" : "华为",
"price" : 4200
}
}
]
},
"aggregations" : { # 聚合数据
"price_group" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 2200,
"doc_count" : 1
},
{
"key" : 3200,
"doc_count" : 1
},
{
"key" : 4200,
"doc_count" : 1
}
]
}
}
}
# 例二:根据price字段聚合(只取聚合数据)
GET /shopping/_search
{
"aggs": { # 聚合操作
"price_group": { # 自定义本次聚合名称(随意取名)
"terms": { # terms代表聚合分组
"field": "price" # 分组字段
}
}
},
"size": 0 # 去掉原始数据(即只取聚合数据)
}
响应:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : { # 聚合数据
"price_group" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 2200,
"doc_count" : 1 # 本次根据price聚合,price为2200的总条数
},
{
"key" : 3200,
"doc_count" : 1
},
{
"key" : 4200,
"doc_count" : 1
}
]
}
}
}
# 例三:求price平均值
GET /shopping/_search
{
"aggs": {
"price_avg": { # 自定义聚合名称
"avg": { # avg 代表求平均值
"field": "price" # price为聚合字段
}
}
},
"size": 0
}
响应:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"price_avg" : { # 平均值
"value" : 3200.0
}
}
}
映射关系(即创建索引时为“字段”指定是否分词,是否支持检索)
# 创建user索引库
PUT /user
# 为user索引库字段指定是否分词,是否能被索引
PUT /user/_mapping
{
"properties":{
"name":{ # 字段name
"type":"text", # text支持分词
"index":true # 支持被检索
},
"sex":{ # 字段sex
"type":"keyword", # keyword不支持分词
"index":true # 支持被检索
},
"tel":{ # 字段tel
"type":"keyword", # 不支持分词
"index":false # 不支持检索
}
}
}
# 为user索引库新加一条记录
PUT /user/_doc/1001
{
"name":"张三",
"sex":"男的",
"tel":"110"
}
# 测试一:测试name支持分词,支持检索
GET /user/_search
{
"query": {
"match": {
"name": "张"
}
}
}
响应:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "user",
"_id" : "1001",
"_score" : 0.2876821,
"_source" : {
"name" : "张三",
"sex" : "男的",
"tel" : "110"
}
}
]
}
}
# 测试二:测试sex不支持分词,支持检索
GET /user/_search
{
"query": {
"match": {
"name": "男" # 因为name字段不支持分词,故传"男"检索不到数据
}
}
}
响应:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
# 测试三:测试tel不支持分词,不支持检索(特别说明:ES8.1.0可以检索到,以前老的ES版本index为false是检索不到的)
GET /user/_search
{
"query": {
"match": {
"tel": "110"
}
}
}
响应:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "user",
"_id" : "1001",
"_score" : 1.0,
"_source" : {
"name" : "张三",
"sex" : "男的",
"tel" : "110"
}
}
]
}
}