GET /_cat/indices?v
PUT /index?pretty
ES的API组成结构:使用RESTful API风格来命名API
API基本格式:http://:/<索引>/<类型>/<文档id> 常用HTTP动词
常用HTTP动词:GET/PUT/POST/DELETE
PUT 执行创建或修改,如确定document的ID时
POST一般用于改变对象或查询,如不确定document的ID,可以直接POST, ES可以 自己生成不会发生碰撞的UUID
GET 一般用于查询
DELETE 用于删除
HEAD 请求获取对象的基础信息,如检查文档是否存在
我们现在有一个业务需求就是存储订单数据,需要创建订单文档,如下操作:
一个文档必须的三个元数据元素如下
_index文档在哪存放
_type文档表示的对象类别
_id文档唯一标识,id可以自己指定,也可以自动生成
是否主键 | 字段名 | 字段描述 | 数据类型 | 分词 |
---|---|---|---|---|
是 | orderId | 订单ID | long | 否 |
否 | userId | 用户ID | long | 否 |
否 | orderNo | 订单号 | string | 否 |
否 | userName | 用户名 | string | 否 |
否 | totalPrice | 价格 | float | 否 |
否 | address | 收货地址 | string | 是 |
否 | createTime | 创建时间 | data | 否 |
如果不创建mapping,ES会根据文档的字段数据自动识别类型 这里需要创建自己定义的mapping
PUT或者POST
PUT /order_index/_mapping/order_type/
{
"order_type": {
"properties": {
"4": {
"type": "text"
},
"access_time": {
"type": "text"
},
"userName": {
"type": "text"
},
"totalPrice": {
"type": "float"
},
"address": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
DELETE /index?pretty
PUT /index/type/id
{
"json数据"
}
es默认会对document每个field都建立倒排索引,让其可以被搜索
bulk api
POST _bulk
{
"index" : {
"_index" : "test", "_type" : "_doc", "_id" : "1" } }
{
"field1" : "value1" }
{
"delete" : {
"_index" : "test", "_type" : "_doc", "_id" : "2" } }
{
"create" : {
"_index" : "test", "_type" : "_doc", "_id" : "3" } }
{
"field1" : "value3" }
{
"update" : {
"_id" : "1", "_type" : "_doc", "_index" : "test"} }
{
"doc" : {
"field2" : "value2"} }
批量插入,如:
POST _bulk
{
"index" : {
"_index" : "order_index", "_type" : "order_type", "_id" : "1" } }
{
"orderId":10001,"userId":10001,"orderNo":"a10001","userName":"John","totalPrice":50.00,"address":"江苏省南京市江宁区XXX","createTime":"2018-05-16 14:08:00"}
{
"index" : {
"_index" : "order_index", "_type" : "order_type", "_id" : "2" } }
{
"orderId":10002,"userId":10002,"orderNo":"a10002","userName":"Jane","totalPrice":80.00,"address":"江苏省南京市鼓楼区XXX","createTime":"2018-05-16 14:30:00"}
{
"index" : {
"_index" : "order_index", "_type" : "order_type", "_id" : "3" } }
{
"orderId":10003,"userId":10003,"orderNo":"a10003","userName":"Douglas","totalPrice":100.00,"address":"江苏省南京市玄武区XXX","createTime":"2018-05-16 14:33:00"}
GET /index/type/id
部分修改相比全量替换的优点: 1.所有查询、修改都是在ES的一个shard中完成的,提升了网络性能 2.减少了查询和修改的时间间隔,减少了并发冲突情况,几乎是毫秒级,部分修改时es内部会自动 执行乐观锁并发控制策略
PUT /index/type/id
{
"json数据"
}
jsonex/type/id/_update
{
"doc": {
"field":""
}
}
DELETE /order_index/order_type/1
DELETE /order_index 删除操作本身很危险,删除索引时会删除它所有的文档数据
PUT /test
{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 5
},
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
},
#嵌套对象
"test1":{
"type": "nested",
"properties": {
"name1":{
"type":"text"
},
"age1":{
"type":"integer"
}
}
}
}
}
}
#创建数据1
POST /test/_doc/111
{
"age":123,
"name":"张三",
"test1":{
"age1":321,
"name1":"李四"
}
}
#创建数据2
POST /test/_doc/222
{
"age":123,
"name":"张三",
"test1":[
{
"age1":321,
"name1":"李四"
},
{
"age1":321,
"name1":"李四"
}
]
}
GET /order_index/order_type/_search
GET /order_index/order_type/1
GET /order_index/order_type/1?pretty
GET /order_index/order_type/1/_source
GET /order_index/order_type/1/_source?orderId,orderNo
GET /order_index/order_type/_search?q=orderId:10001
POST /order_index/order_type/_search
{
"query": {
"match": {
"orderId": 10001
}
}
}
POST /order_index/order_type/_search
{
"query": {
"match_all": {
} },
"from": 10,
"size": 10
}
POST /order_index/order_type/_search
{
"query": {
"match_all": {
}
},
"sort": {
"orderId": {
"order": "desc"
},
"userId": {
"order": "desc"
}
}
}
POST _mget
{
"docs": [
{
"_index": "order_index",
"_type": "order_type",
"_id": 1
},
{
"_index": "order_index",
"_type": "order_type",
"_id": 2
}
]
}
_all字段是把所有其它字段中的值,以空格为分隔符组成一个大字符串,_all能让你在不知道要查找的内容是属于哪个具体字段的情况下进行搜索 query_string 和 simple_query_string 查询默认都是查询 _all 字段
POST /order_index/order_type/_search
{
"query": {
"query_string": {
"query": "鼓楼"
}
}
}
等同于:
GET /order_index/order_type/_search?q=鼓楼
了解以下查询关键词: match_all match multi_match match_phrase range term和terms bool查询包含:must、must_not、should、filter wildcards regexp prefix Phrase Matching
分页查询文档
GET /index/type/_search
{
"query": {
"match_all": {
} },
"from": 1,
"size": 1
}
highlight 高亮搜索文档,会将搜索词高亮显示
GET /index/type/_search
{
"query" : {
"match" : {
"producer" : "producer"
}
},
"highlight": {
"fields" : {
"producer" : {
}
}
}
}
对所有文档查询,默认查询前10条数据,按_score降序排序
POST /order_index/order_type/_search
{
"query": {
"match_all": {
}
}
}
match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。 但只能针对一个字段。 如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符
POST /order_index/order_type/_search
{
"query": {
"match": {
"address": "鼓楼区"
}
}
}
如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将为你搜索你给定的值: 如:
{
"match": {
"totalPrice": 26 }}
{
"match": {
"createTime": "2014-09-01" }}
{
"match": {
"public": true }}
{
"match": {
"userName": "Jane" }}
multi_match查询允许你做match查询的基础上同时多个字段搜索同一个,相当于or查询
POST /order_index/order_type/_search
{
"query": {
"multi_match": {
"query": "Jane",
"fields": [
"userName",
"address"
]
}
}
}
match_phrase 短语搜索文档 要求输入的搜索词,必须在指定的字段文本中,完全包含一模一样的,才可以作为结果返回
POST /order_index/order_type/_search
{
"query": {
"match_phrase": {
"address": "鼓楼区"
}
}
}
range过滤允许我们按照指定范围查找一批数据 gt :: 大于 gte:: 大于等于 lt :: 小于 lte:: 小于等于
POST /order_index/order_type/_search
{
"query": {
"bool": {
"filter": {
"range": {
"totalPrice": {
"gt": 20,
"lt": 80
}
}
}
}
}
}
term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分词的文本数据类型)
POST /order_index/order_type/_search
{
"query": {
"bool": {
"filter": {
"term": {
"totalPrice": 100
}
}
}
}
}
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配
POST /order_index/order_type/_search
{
"query": {
"bool": {
"filter": {
"terms": {
"totalPrice": [
100,
80
]
}
}
}
}
}
Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
must 返回的文档必须满足must子句的条件,并且参与计算分值
filter 返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
should 返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。
must_not 返回的文档必须不满足must_not定义的条件。
POST /order_index/order_type/_search
{
"query": {
"bool": {
"must": {
"match": {
"address": "南京市"
}
},
"must_not": {
"match": {
"totalPrice": "50"
}
},
"should": [
{
"match": {
"totalPrice": "80"
}
},
{
"range": {
"createTime": {
"gte": "2018-05-15 14:31:00"
}
}
}
]
}
}
}
使用标准的shell通配符查询
POST /order_index/order_type/_search
{
"query": {
"wildcard": {
"address": "南?市*"
}
}
}
正则表达式查询
POST /order_index/order_type/_search
{
"query": {
"regexp": {
"orderNo": "a[0-9]+"
}
}
}
以什么字符开头的,可以更简单地用 prefix
POST /order_index/order_type/_search
{
"query": {
"prefix": {
"address": "江"
}
}
}
聚合查询需要设置size如果不设置size会查询出其他数据消耗性能
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"return_totalPrice": {
"sum": {
"field": "totalPrice"
}
}
}
}
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"return_avg_totalPrice": {
"avg": {
"field": "totalPrice"
}
}
}
}
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"return_min_totalPrice": {
"min": {
"field": "totalPrice"
}
}
}
}
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"return_max_totalPrice": {
"max": {
"field": "totalPrice"
}
}
}
}
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"return_stats_totalPrice": {
"stats": {
"field": "totalPrice"
}
}
}
}
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"group_by_totalPrice": {
"terms": {
"field": "totalPrice"
}
}
}
}
比如按totalPrice升序,按orderId分组
#aggs聚合 totalPrice只是一个名字 terms过滤 field 条件也可以写script脚本进行聚合查询
POST /order_index/order_type/_search
{
"size": 0,
"aggs": {
"totalPrice": {
"terms": {
"field": "totalPrice",
"order": {
"_count": "asc"
}
}
},
"group_by_totalPrice": {
"terms": {
"field": "orderId"
}
}
}
}
嵌套聚合查询
GET /event-20210514134033531/_search
{
"aggs":{
"my_name":{
"terms":{
"field":"lid",
"size":1000
},
"aggs":{
"my_name1":{
"terms":{
"field":"csip_country_name.keyword",
"size":1000
},
"aggs":{
"my_name3":{
"terms":{
"field":"csip_region_name.keyword",
"size":1000
}
}
}
}
}
}
},
"from":1,
"size":0
}
//结果
{
"my_name":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":38128,
"buckets":[
{
"key":5638138383101068,
"doc_count":1,
"my_name1":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":0,
"buckets":[
{
"key":"中国",
"doc_count":1,
"my_name3":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":0,
"buckets":[
{
"key":"江苏省",
"doc_count":1
}
]
}
}
]
}
}
]
}
}
查询DSL有2种:查询DSL(query DSL)和过滤DSL(filter DSL) 为什么filter会快?
查询在Query查询上下文和Filter过滤器上下文中,执行的操作是不一样的:
Query查询上下文:
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?” 如何验证匹配很好理解,如何计算相关度呢?之前说过,ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。 查询上下文 是在 使用query进行查询时的执行环境,比如使用search的时候。
Filter过滤器上下文: 在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?” 答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。 过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用Must_not或者filter。
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
{
"query": {
"bool": {
"must": [
{
"match": {
"tags.name": "VPN"
}
}
]
}
}
}
{
"_index": "asset",
"_type": "_doc",
"_id": "501",
"_score": 1.0,
"_source": {
"tags": [
{
"color": "#33d780",
"name": "VPN"
}
],
"grade": 0,
"name": "VPN设备",
"interfaceInfo": [
{
"ip": "10.67.7.67",
"mac": ""
}
],
"status": 1
}
}
给order表添加关联字段
如果有多个集合
{
"doc": {
"user": [
{
"userId": "2",
"userName": "bbb",
"mobile": "138******13",
"age": "28",
"sex": "M"
},
{
"userId": "1",
"userName": "aaa",
"mobile": "138******12",
"age": "27",
"sex": "F"
}
]
}
}
查询结果
POST /order_index/order_type/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"orderNo": "a10001"
}
},
{
"match": {
"user.userId": 1
}
},
{
"match": {
"user.age": 27
}
}
]
}
}
}