// 准备数据
PUT /shop/goods/1
{"name": "2017新款女装冬季外套ulzzang棉袄中长款棉衣韩版百搭棉服面包服","desc": "","price": 268,"quantity": 9267,"colors": ["绿色","黑色"],"is_discount": true,"create_date": "2018-01-31 12:10:30","ip_addr": "192.168.10.1","location": "39.92733,116.39507","merchant": {"id": 999,"shop_name": "阿依莉旗舰店"},"params": [{"id": 1,"label": "型号","value": "A30566"},{"id": 2,"label": "品牌","value": "阿依莉"}],"activity": "买一送一"
}PUT /shop/goods/2
{"name": "2018春季长袖t恤女加绒加厚圆领宽松套头毛衣女装韩版学生毛线衣","price": 108,"quantity": 268,"colors": ["白蓝红","红白黑"],"is_discount": false,"create_date": "2017-01-31 12:10:30","ip_addr": "192.168.10.1","location": "39.92733,116.39507","merchant": {"id": 6666,"shop_name": "美特斯邦威旗舰店"},"params": [{"id": 1,"label": "型号","value": "HWT8030"},{"id": 2,"label": "品牌","value": "美特斯邦威"}]
}PUT /account/users/1
{"username": "xiaoming","nickname": "小明的老师","age": 6,"height": 1.68,"birthday": "2017-01-31","hobbies": ["吃", "喝", "嫖", "赌"]
}PUT /accounts/users/1
{"username": "teacher","nickname": "谁能求姐","age": 6,"height": 1.68,"birthday": "2017-01-31","hobbies": ["批评小明"]
}

_search

注意:_search即支持GET也支持POST

GET /_search  // 空查询:查询所有索引下的所有文档
GET /{index}/_search       // 查询某个索引下的前10条文档
GET /{index}/{type}/_search  // 查询某个索引下某个类型的前10条文档

// 返回结果
took字段表示该操作的耗时(单位为毫秒),
timed_out字段表示是否超时,
_shards:在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个
total:返回记录数,本例是2条。
max_score:最高的匹配程度,本例是1.0。
hits:返回的记录组成的数组。
返回的记录中,每条记录都有一个_score字段,表示匹配的程序,默认是按照这个字段降序排列。

多索引,多类型
GET /{index1},{index2}/_search  // 查询多个索引下的文档
GET /{index*}/_search           // 索引支持*号通配符
GET /{index*},{index*}/_search
GET /_all/_search  // 和GET /_search效果一样,_all:表示所有索引GET /{index}/{type1},{type2}/_search
// 示例
GET /_search
GET /shop/_search
GET /shop/goods/_search
POST /shop/goods/_search
GET /shop,account/_search
GET /account*/_search
GET /account*,sho*/_search
GET /_all/_search
GET /shop/goods,products/_search

查询字符串

查询字符串:就是在_search上使用GET参数的形式对search进行查询过滤,即将参数追加到路径上,此种方式有局限性,不够灵活

  • q: 通过加号+来指定查询中的某个字段必须包含某个值,默认是加号,通过减号-来指定文档中不能包含某个值,使用冒号将字段和值分隔,如 q=last_name:Smith,类似于关系型数据库中的where中的 like和not like 操作,
  • _source:用于指定要查询的字段,默认会返回文档中的所有字段,多个字段用逗号分隔
  • size: 设置search是返回的消息的条数,默认是10
  • from: 设置跳过的页数,默认是0,可以通过from和size来达到分页的目的
  • sort: 指定对那个字段进行什么排序,默认是按照相关性评分来降续排序的_score, 例如sort=date:desc&sort=_score
  • version: 版本号,用于更新和删除操作,当文档的版本等于指定的版本号时才能正常执行,否则会返回409 版本冲突 (乐观并发控制)
  • ersion_type=external 用于创建、修改、删除操作 外部版本号:当使用外部版本号是es会检查版本号是否比_version值小,如果小的话就正常执行,并将_version的值更改为外部的版本号, 例如version=5&version_type=external
  • timeout=10ms 指定超时时间,默认单位是毫秒ms,也可以指定秒s,例如1s
  • retry_on_conflict=n 参数来设置自动完成这项请求的次数,它的默认值是0,失败前重新尝试n次
  • scroll=1m 游标查询,保持游标查询窗口一分钟
// q好像对中文查询不出啦???可以通过其他方式进行查询
// 查询字段包含的字符串q=filed:value, 类似于SQL中的where last_name like '%Smith%'
GET /{index}/{type}/_search?q=last_name:Smith                     // 加号+:表示必须存在,每部分都是包含的意思, 类似于SQL中的where fist_name like '%join%' and like '%Smith%'
// + 前缀表示必须与查询条件匹配。类似地, - 前缀表示一定不与查询条件匹配。
// 没有 + 或者 - 的所有其他条件都是可选的,类似于or——匹配的越多,文档就越相关
GET /{index}/{type}/_search?q=fist_name:join+last_name:Smith'    // -号代表不包含, 类似于SQL中的 where name not like '%join%'
GET /{index}/{type}/_search?q=-name:join   // name包含join但tweet不包含jmary的, 类似于SQL中的 where name like '%join%' and tweet not like '%mary%'
GET /{index}/{type}/_search?q=name:join+-tweet:mary     // 查询所有索引所有类型所有字段中包含mary关键字的文档, _all:可以代表所有索引或者所有类型或者所有字段,
// 每个文档都有一个隐形的_all字段,它的数据类型是文本型,它的值是以空格的形式将文档的所有字段的值拼接起来, 例如一个文档有三个值 age: 15, name:zhangsan, birthday:2018-09-15, 那么_all的值为“15 zhangsan 2018-09-15”
// _all会被分词,如果字段中包含日期,例如2018-09-15会被分析成2018,09, 15 三个词条(token)
GET /{index}/{type}/_search?q=_all:mary  // 如果不指定字段则默认是_all字段, _all字段是String类型
GET /{index}/{type}/_search?q=mary   POST /shop/goods/_search?_source=name,pricePOST /shop/goods/_search?timeout=10ms   POST /shop/goods/_search?from=0&size=5    POST /shop/goods/_search?sort=create_date:desc&sort=_score                    

查询表达式DSL

使用查询领域特定语言(Query Domain Specific Language) 简称为DSL, 需要使用JSON作为主体,请求体查询

  • query

    • match:模糊匹配,类似于SQL中的like,示例{ “match” : { “field” : “keyword” }},
    • match_all:简单的匹配所有文档 {“match_all”: {}}
    • match_phrase: 对于短语或者段落进行精确匹配
    • match_phrase_prefix
    • multi_match: 在多个字段上反复执行相同查询
    • bool 用于表示复合语句,用于组合多个查询语句;将多查询组合成单一查询
      • must 必须匹配这些条件才能被包含进来,表示并且的关系
      • must_not 必须不 匹配这些条件才能被包含进来
      • should 如果满足这些语句中的任意语句,将增加 _score ,否则无任何影响。它们主要用于修正每个文档的相关性得分。
      • minimum_should_match:控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比, 如 minimum_should_match: 2 或者 “minimum_should_match”: “75%”
      • filter 必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档, filter只是简单的数据过滤,并不影响评分,因filter不计算评分,所以性能更好,请尽可能多的使用过滤式查询
        • exists 查找包含某个字段的文档
    • range 范围,可以使用大于gt、大于等于gte、小于lt、小于等于lte作为查询条件,可用于数字、日期类型、字符串
    • term 精确查询,对数值,日期,布尔,not_analyzed确切值字符串
    • terms 指定多个匹配值,如果字段包含其中的任何一个,都会返回文档,类似于SQL中的IN 操作
    • constant_score: 恒定分数,它将一个不变的常量评分应用于所有匹配的文档
    • wildcard: 通配符, ? 匹配任意字符, * 匹配 0 或多个字符
    • fuzzy: 模糊查询
    • dis_max:分离 最大化查询(Disjunction Max Query)
    • nested : 用于操作嵌套类型
  • highlight 高亮,匹配的结果会被 HTML字符包裹住,需要指定匹配的字段

  • aggs 聚合操作,类似SQL中的Group By
  • sort 排序
  • from 偏移量,类似于SQL中limit中的offset
  • size 返回数量,类似于SQL中limit中的count,可以通过from,size来达到分页的效果
// 使用DSL查询肯能条件很多,比较复杂,可以通过使用验证API来检查一个查询是否有效
GET /{index}/{type}/_validate/query?explain
{  "query": {  ... }
} 

数据准备

DELETE /shop/goods/_all 删除所有文档

match 匹配查询

全文检索方式查询,类似于关系型数据库中的like操作,使用match时需要指定对那个字段进行全文检索,以及对应的关键字, 关键字可以指定一个也可以指定多个,指定多个时表示或者的关系 类似于SQL中的or的功能。语法:
{ "match" : { "field" : "keyword" }} 类似于SQL中的where filed like ‘%keyword%’
{ "match" : { "field" : "keyword1 keyword2" }} 类似于SQL中的where field like ‘%keyword1%’ or field like ‘%keyword2%’

示例:

// 查询name中包含“女装”的文档

GET /shop/goods/_search
{"query": {"match": {"name": "女装"}}
}// 多词查询 :使用空格隔离多个单词
// 查询name中包含“外套” 或者or 包含 “休闲” 的文档,多个关键字使用空格分隔,如果不指定operator默认是or
GET /shop/goods/_search
{"query": {"match": {"name": "外套 休闲"}}
}// "name": "外套 休闲" or 等价于bool中的should
GET /shop/goods/_search
{"query": {"bool": {"should": ["match": { "name": "外套" },"match": { "name": "休闲" },]}}
}// 查询name中包含“外套” 并且 包含 “休闲” 的文档,多个关键字使用空格分隔
GET /shop/goods/_search
{"query": {"match": {"name": "外套 休闲","operator": "and"}}
}// "name": "外套 休闲" and 等价于bool中的must
GET /shop/goods/_search
{"query": {"bool": {"must": ["match": { "name": "外套" },"match": { "name": "休闲" },]}}
}// 多词查询中使用or只需要满足一个即可,要求太低,使用and又必须所有词项都必须满足,要求又太高,
// 使用minimum_should_match折中一下,最小匹配:可以指定一个百分比,
// 例如指定4个词项,一个是词项是25%,设置成50%就是至少要满足2个词项
GET /shop/goods/_search
{"query": {"match": {"name": {"query": "春季 长袖 圆领 学生","minimum_should_match": "50%"}}}
}// 效果和上面一样,等价的
GET /shop/goods/_search
{"query" : {"bool": {"filter": {"bool" : {"should" : [{ "term" : {"name" : "春季"}}, { "term" : {"name" : "长袖"}}, { "term" : {"name" : "圆领"}}, { "term" : {"name" : "学生"}}],"minimum_should_match": 2}}}}
}// 查询日期
GET /shop/goods/_search
{"query": {"match": {"create_date": "2018-01-31"}}
}

match一般用于用引号括起来的值,如文本,日期,如果将match用于布尔或者数字等数据类型就变成精确匹配了,而不是全文检索或者模糊匹配了
如果在一个精确值的字段上使用match,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:

match_all

简单的匹配所有文档

GET /shop/goods/_search
{"query": {"match_all": {}}
}// 上面简写成这样,效果是一样的
GET /shop/goods/_search
{}// 同样也可以去掉{},更加简洁
GET /shop/goods/_search 

match_phrase

对于短语或者段落进行精确匹配,

// match如果对一小段文本进行查询,match首先对字段值进行分词,然后对分词进行匹配,相当于SQL中的name like '%女装%' or name like '%冬季%' or name like '%外套%'
GET /shop/goods/_search
{"query": {"match": {"name": "女装冬季外套"}}
}GET /shop/goods/_search
{"query": {"match_phrase": {"name": "女装冬季外套"}}
}

// slop:让相对词序位置不那么严格
// 注意上面使用的是“女装冬季外套”,而现在使用的是“套女装冬季”, slop:允许每个词放宽的间隔
// 尽管词语的顺序不正确,查询仍然能匹配,因为我们为它设置了足够高的slop值使匹配时的词序有更大的灵活性。
GET /shop/goods/_search
{"query": {"match_phrase": {"name": {"query": "外套女装冬季","slop":  10}}}
}

match_phrase_prefix

match_phrase_prefix与match_phrase是一样的,只是它允许在文本的最后一项中使用前缀匹配。

可以用于即时搜索(instant search) 或 输入即搜索(search-as-you-type),例如,如果用户输入 johnnie walker bl ,我们希望在它们完成输入搜索条件前就能得到:Johnnie Walker Black Label 和 Johnnie Walker Blue Label 。

GET /shop/goods/_search
{"query": {"match_phrase_prefix": {"name": "女装冬季外套"}}
}// slop:让相对词序位置不那么严格
// 注意上面使用的是“女装冬季外套”,而现在使用的是“套女装冬季”, slop:允许每个词放宽的间隔
// 尽管词语的顺序不正确,查询仍然能匹配,因为我们为它设置了足够高的slop值使匹配时的词序有更大的灵活性。
GET /shop/goods/_search
{"query": {"match_phrase_prefix": {"name": {"query": "外套女装冬季","slop":  10}}}
}

prefix 查询存在严重的资源消耗问题,短语查询的这种方式也同样如此。前缀 a 可能会匹配成千上万的词,这不仅会消耗很多系统资源,而且结果的用处也不大。

索引时输入即搜索

## edge_ngram 自定义过滤器、分词器
PUT /my_index
{"settings": {"number_of_shards": 1, "analysis": {"filter": {"autocomplete_filter": { "type":     "edge_ngram","min_gram": 1,"max_gram": 20}},"analyzer": {"autocomplete": {"type":      "custom","tokenizer": "standard","filter": ["lowercase","autocomplete_filter" ]}}}}
}## 测试分词
GET /my_index/_analyze
{"analyzer": "autocomplete","text": "quick brown"
}PUT /my_index/_mapping/my_type
{"my_type": {"properties": {"name": {"type":     "text","analyzer": "autocomplete",  ## 使用自定义的分词器"search_analyzer": "standard" ## 配置查询对应的分词器}}}
}POST /my_index/my_type/_bulk
{ "index": { "_id": 1            }}
{ "name": "Brown foxes"    }
{ "index": { "_id": 2            }}
{ "name": "Yellow furballs" }## 搜索
GET /my_index/my_type/_search
{"query": {"match": {"name": {"query":    "brown fo"}}}
}

multi_match

多个字段上使用相同的值作为查询条件

GET /shop/goods/_search
{"query": {"multi_match": {"query": 268,"fields": ["price", "quantity"]}}
}// 两者效果相同
GET /shop/goods/_search
{"query": {"bool": {"should": [{ "term": { "price": { "value": 268 } } },{ "term": { "quantity": { "value": 268 } } }]}}
}// 查询字段名称的模糊匹配
// 字段名称可以用模糊匹配的方式给出:任何与模糊模式正则匹配的字段都会被包括在搜索条件中,
例如可以使用以下方式同时匹配 book_title 、 chapter_title 和 section_title (书名、章名、节名)这三个字段:{"multi_match": {"query":  "Quick brown fox","fields": "*_title"}
}// 提升单个字段的权重
// 可以使用 ^ 字符语法为单个字段提升权重,在字段名称的末尾添加 ^boost ,其中 boost 是一个浮点数:
// chapter_title 这个字段的 boost 值为 2 ,而*_title 字段的默认 boost 值为 1
{"multi_match": {"query":  "Quick brown fox","fields": [ "*_title", "chapter_title^2" ] (1)}
}

constant_score 常量分数

通常当查找一个精确值的时候,我们不希望对查询进行评分计算。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分。

它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助. 这种方式可以用来取代只有 filter 语句的 bool 查询


GET /shop/goods/_search
{"query": {"constant_score": {"filter": {"term": {"price": 268.00}}}}
}

查询置于 filter 语句内不进行评分或相关度的计算,所以所有的结果都会返回一个默认评分 1

prefix 前缀查询

前缀查询:要查询的字段必须没有分词

默认状态下, prefix 查询不做相关度评分计算,它只是将所有匹配的文档返回,并为每条结果赋予评分值 1 。它的行为更像是过滤器而不是查询。 prefix 查询和 prefix 过滤器这两者实际的区别就是过滤器是可以被缓存的,而查询不行。

prefix 查询或过滤对于一些特定的匹配是有效的,但使用方式还是应当注意。当字段中词的集合很小时,可以放心使用,但是它的伸缩性并不好,会对我们的集群带来很多压力。可以使用较长的前缀来限制这种影响,减少需要访问的量。

PUT /my_index
{"mappings": {"address": {"properties": {"postcode": {"type":  "keyword"}}}}
}PUT /my_index/address/1
{ "postcode": "W1V 3DG" }PUT /my_index/address/2
{ "postcode": "W2F 8HW" }PUT /my_index/address/3
{ "postcode": "W1F 7HW" }PUT /my_index/address/4
{ "postcode": "WC1N 1LZ" }PUT /my_index/address/5
{ "postcode": "SW5 0BE" }// prefix 查询
GET /my_index/address/_search
{"query": {"prefix": {"postcode": {"value": "W1"}}}
}

wildcard 和 regexp

与 prefix 前缀查询的特性类似, wildcard 通配符查询也是一种底层基于词的查询,与前缀查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符。

GET /my_index/address/_search
{"query": {"wildcard": {"postcode": "W?F*HW" }}
}// 词必须以 W 开头,紧跟 0 至 9 之间的任何一个数字,然后接一或多个其他字符
GET /my_index/address/_search
{"query": {"regexp": {"postcode": "W[0-9].+" }}
}

wildcard 和 regexp 查询的工作方式与 prefix 查询完全一样,它们也需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID ,与 prefix 查询的唯一不同是:它们能支持更为复杂的匹配模式。

这也意味着需要同样注意前缀查询存在性能问题,对有很多唯一词的字段执行这些查询可能会消耗非常多的资源,所以要避免使用左通配这样的模式匹配(如: *foo 或 .*foo 这样的正则式)。

数据在索引时的预处理有助于提高前缀匹配的效率,而通配符和正则表达式查询只能在查询时完成,尽管这些查询有其应用场景,但使用仍需谨慎。

prefix 、 wildcard 和 regexp 查询是基于词操作的,如果用它们来查询 analyzed 字段,它们会检查字段里面的每个词,而不是将字段作为整体来处理。


range

用于查询一个区间,一般用于日期和数值,支持 gt、gte、lt、lte, 示例{“range”: { “age”: { “gte”: 20, “lt”:30 }}} 类似于SQL中的 wher age >= 20 and age < 30

GET /shop/goods/_search
{"query": {"range": {"price": {"gt": 200,"lte": 500}}}
}// 日期类型
GET /shop/goods/_search
{"query": {"range": {"create_date": {"gt" : "2014-01-01 00:00:00","lt" : "2014-01-07 00:00:00"}}}
}// 日期计算:过去一小时
GET /shop/goods/_search
{"query": {"range": {"create_date": {"gt" : "now-1h"}}}
}// 日期计算:早于 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零时)
GET /shop/goods/_search
{"query": {"range": {"create_date": {"gt" : "2014-01-01 00:00:00","lt" : "2014-01-01 00:00:00||+1M"}}}
}// 作用于字符串,性能相对较慢
"range" : {"title" : {"gte" : "a","lt" :  "b"}
}

term

精确查询:用于精确值匹配,对数值,日期,布尔,not_analyzed确切值字符串, term 查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。

GET /shop/goods/_search
{"query": {"term": {"is_discount": {"value": true}}}
}

terms

同term查询,但是它允许指定多个匹配值,一般用于数组,如果字段包含其中的任何一个,都会返回文档, 类似于where tag IN (‘value1’, ‘value2’, ‘value3’) 例如:{ “terms”: { “tag”: [ “search”, “full_text”, “nosql” ] }}

GET /shop/goods/_search
{"query": {"terms": {"colors": ["白蓝红","绿色"]}}
}

exists

对于相同类型的文档,可能有的文档有某个字段,有的文档没有某个字段,查找包含或者不包含某个字段的文档, 例如: {“exists”: { “field”: “title” }} ,exists 用于查找那些指定字段中是否有值 , 相当于SQL中的IS NOT NULL

null, [] (空数组)和 [null] 所有这些都是等价的,它们无法存于倒排索引中

这些查询经常用于某个字段有值的情况和某个字段缺值的情况。

// 存在某个字段
GET /shop/goods/_search
{"query": {"bool": {"filter": {"exists": {"field": "activity"}}}}
}// 不存在某个字段
GET /shop/goods/_search
{"query": {"bool": {"must_not": {"exists": {"field": "activity"}}}}
}POST /my_index/posts/_bulk
{ "index": { "_id": "1"              }}
{ "tags" : ["search"]                }
{ "index": { "_id": "2"              }}
{ "tags" : ["search", "open_source"] }
{ "index": { "_id": "3"              }}
{ "other_field" : "some data"        }
{ "index": { "_id": "4"              }}
{ "tags" : null                      }
{ "index": { "_id": "5"              }}
{ "tags" : ["search", null]          }以上文档集合中 tags 字段对应的倒排索引如下:
Token DocIDs
open_source 2
search 1,2,51. tags 字段有 1 个值。
2. tags 字段有 2 个值。
3. tags 字段缺失。
4. tags 字段被置为 null 。
5. tags 字段有 1 个值和 1 个 null 。// 1,2,5 满足条件
GET /my_index/posts/_search
{"query" : {"constant_score" : {"filter" : {"exists" : { "field" : "tags" }}}}
}

highlight:高亮

匹配的结果会被 HTML字符包裹住,需要指定匹配的字段,”highlight”: {“fields” : {“about” : {}}}

// 高亮: 匹配的结果会被 <em></em> HTML字符包裹住:
curl -i -H 'Content-Type: application/json'  -XGET 'http://localhost:9200/megacorp/employee/_search' -d '
{"query" : {"match_phrase" : {"about" : "rock climbing"}},"highlight": {"pre_tags" : ["<font color='red'>"],"post_tags" : ["</font>"],"fields" : {"about" : {}}}
}'

sort

排序,可以指定一个或者多个字段排序,多个字段使用数组包围,例如:”sort”: { “date”: { “order”: “desc” }}

// 排序,默认情况下是按照相关性评分排序的,最相关的文档排在最前, 默认按_score排序的
// 多级排序,使用date, _score排序
GET /_search
{  "query" : {  "bool" : {  "must":   { "match": { "tweet": "manage text search" }},  "filter" : { "term" : { "user_id" : 2 }}  }  },  "sort": [  { "date":   { "order": "desc" }},  { "_score": { "order": "desc" }},{ "ids" : { "order": "asc", "mode":  "min"}}  ]
}  mode:一般用于数组,可以使用min 、 max 、 avg 或是 sum,统计计算数组的指定值排序

对字符串排序,sort对字符串排序需要使用到原始值raw,正常情况下文本可能会使用分词器进行分词,而分词器会影响正常的排序,这时可以对同一个字段设置两种类型,对文本设置成text类型,并设置分词器,如果要搜索的话使用text类型字段,然后再为该字段设置一个原始值,该原始值raw字段的fields的数据类型设置为keyword,关键字数据类型是不分词的,不分词的字段可以作为字符串的排序

// fields 多字段:相当于对同一个字段值起不同的名字,赋予这个字段不同的属性(如类型不同,分词器不同等)
PUT /school
{"mappings": {"students": {"properties": {"name": {"type": "text","analyzer": "ik_max_word","fields": {"raw": {"type": "keyword"}  }}}}}
}// _score 和 max_score 字段都是 null 。计算 _score 的花销巨大,通常仅用于排序; 我们并不根据相关性排序,所以记录 _score 是没有意义的。如果无论如何你都要计算 _score , 你可以将 track_scores 参数设置为 true
GET /school/students/_search
{"query": { "match": { "name": "abc" } }, "sort": [ { "name.raw": { "order": "desc" } } ]
}// 强制计算评分
GET /school/students/_search
{"track_scores": true,"query": { "match": { "name": "abc" } }, "sort": [ { "name.raw": { "order": "desc"} } ]
}

from

偏移量,类似于SQL中limit中的offset

size

返回数量,类似于SQL中limit中的count,可以通过from,size来达到分页的效果

GET /shop/goods/_search
{"from": 0,"size": 20
}

游标查询Scroll

使用from, size做分页不能分页太深,太深对性能营销较大,一般获取前1000条数据就算深了,游标查询用于解决深度分页带来的性能问题。

scroll 查询可以用来对Elasticsearch有效地执行大批量的文档查询,而又不用付出深度分页那种代价。游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的 cursor 。游标查询会取某个时间点的快照数据,查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引 ‘视图’ 一样。

深度分页的代价根源是结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。 游标查询用字段_doc来排序。 这个指令让 Elasticsearch 仅仅从还有结果的分片返回下一批结果。启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间,游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。

// 保持游标查询窗口一分钟
// 关键字 _doc 是最有效的排序顺序。
GET /shop/goods/_search?scroll=1m
{"query": {"match_all": {}},"sort": ["_doc"],"size": 1000
}// 这个查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串 。 现在我们能传递字段 _scroll_id 到 _search/scroll
{"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAMoFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADKRZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAyoWZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAMrFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADLBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn","took": 1,"timed_out": false,...
}// 查询接口获取下一批结果:
GET /_search/scroll
{"scroll": "1m","scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAKbFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAp0WZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAKeFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnxZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn"
}

这个游标查询返回的下一批结果。 尽管我们指定字段 size 的值为1000,我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards.

注意游标查询每次返回一个新字段 _scroll_id。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段 _scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。

bool

布尔查询,这是一个很重要的查询,它可以将其它多种查询封装成一个大的查询,可以使用逻辑操作符(类似于sql中的and、not、or)来组装各个条件, 这是个复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合

用于表示复合语句,用于组合多个查询语句;将多查询组合成单一查询,bool可以放到query下面,也可以嵌套在某个子条件(must、should、must_not)里, 通过嵌套可以构造出更加复杂的过滤条件。

  • must: 必须匹配这些条件才能被包含进来。 表示并且的关系,与 SQL中的AND 等价,例如{"must": [{"match": {"desc": "xxx"}}, {"term": { "quantity": 999}}]},类似于SQL中的where desc like '%xxx%' and quantity = 999
  • must_not: 必须不匹配这些条件才能被包含进来, 是对must的取反操作,与SQL中的 != 或者<> 等价, where status != 0
  • should 至少有一个语句要匹配, 与 SQL中的 OR 等价,是一个数组,可以有多个值,如果满足这些语句中的任意语句,将增加_score的值, should的作用:or逻辑,如果满足条件评分_score更高
  • filter:必须匹配,以过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档, filter只是简单的数据过滤,并不影响评分
  • minimum_should_match

bool 查询会为每个文档计算相关度评分 _score ,再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。

must_not 语句不会影响评分;它的作用只是将不相关的文档排除。

所有must语句必须匹配,所有must_not语句都必须不匹配,经测试至少有一个should需要匹配的(在should中写两个条件,每天条件都不满足条件,结果没有任何文档满足),当没有 must 语句的时候,至少有一个 should 语句必须匹配。

GET /shop/goods/_search
{"query": {"bool": {"must": [{"term": {"quantity": {"value": 999}}}], "must_not": [{"term": {"quantity": {"value": 9267}}}],"should": [{"term": {"is_discount": {"value": true}}}],"filter": {"range": {"price": {"gte": 7777,"lte": 9999}}}}}
}
// filter中也可以嵌套bool查询,这样内部的bool查询就不参与评分了
// bool中的must must_not should 等会计算评分的,如果不希望计算评分,可将bool放入到filter中,这样既不计算评分又可以使用bool中的逻辑
// 直接使用bool中的filter和将bool再次嵌入到filter中都不计算评分
GET /shop/goods/_search
{"query": {"bool": {"must":     { "match": { "title": "how to make millions" }},"must_not": { "match": { "tag":   "spam" }},"should": [{ "match": { "tag": "starred" }}],"filter": {"bool": { "must": [{ "range": { "date": { "gte": "2014-01-01" }}},{ "range": { "price": { "lte": 29.99 }}}],"must_not": [{ "term": { "category": "ebooks" }}]}}}}
}// 就像我们能控制 match 查询的精度 一样,我们可以通过 minimum_should_match 参数控制需要匹配的
// should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比:
// 这个查询结果会将所有满足以下条件的文档返回:
// title 字段包含 "brown" AND "fox" 、 "brown" AND "dog" 或 "fox" AND "dog" 。
// 如果有文档包含所有三个条件,它会比只包含两个的文档更相关。
GET /my_index/my_type/_search
{"query": {"bool": {"should": [{ "match": { "title": "brown" }},{ "match": { "title": "fox"   }},{ "match": { "title": "dog"   }}],"minimum_should_match": 2 }}
}// boost 参数被用来提升一个语句的相对权重( boost 值大于 1 )或降低相对权重( boost 值处于 0 到 1 之间),
// 但是这种提升或降低并不是线性的,换句话说,如果一个 boost 值为 2 ,并不能获得两倍的评分 _score 。
// 通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。
// 更高的 boost 值为我们带来更高的评分 _score
GET /_search
{"query": {"bool": {"must": {"match": {  "content": {"query":    "full text search","operator": "and"}}},"should": [{ "match": {"content": {"query": "Elasticsearch","boost": 3 }}},{ "match": {"content": {"query": "Lucene","boost": 2 }}}]}}
}

过滤查询:不需要评分,性能更好,对结果进行缓存
评分查询:需要评分,评分比较费力,不对结果进行缓存
如何选择查询与过滤? 通常的规则是,使用查询(query)语句来进行 全文搜索或者其它任何需要影响相关性得分的搜索。除此以外的情况都使用过滤(filters)。

aggs

聚合操作,类似SQL中的Group By, 支持的聚合类型有avg, min, max, sum, rang 等,也可以对地理位置进行聚合

如果要对一个字段进行聚合,要保证这个字段的fielddata设置为true

PUT /{index}/_mapping/{type}
{"properties": {"FILED": {"type": "text","fielddata": true}}
}
// 统计数组中每个元素出现的次数,中文有问题,现在中文分词是按单个字分词的,估计需要指定对该字段不分词
GET /shop/goods/_search
{"aggs": {"xxx": {"terms": {"field": "colors","size": 10}}}
}// aggs可以嵌套在aggs中使用
// 嵌套聚合,分级汇总,在聚合中可以进行再聚合,意思是对分组的文档进行其他聚合,而不是对聚合结果进行处理
GET /shop/goods/_search
{"aggs": {"xxx": {"terms": {"field": "colors","size": 10},"aggs": {"yyy": {"avg": {"field": "price"}}}}}
}

_mget

multi-get,通过docs数组作为参数指定多个doc来获取多个文档,每个doc可以分别指定索引、类型、id,文档或者api中必须包含index/type/id

// 路径中不包含index、type、id
GET /_mget
{"docs" : [{"_index" : "shop","_type" :  "goods","_id" :    2},{"_index" : "account","_type" :  "users","_id" :    1,"_source": "nickname"}]
}// 路径中包含index、type, 如果参数中没有指定index、type就使用路径中的,如果参数中明确指定了,就使用参数中的索引和类型
GET /{index}/{type}/_mget
{"docs" : [{ "_id" : 2 },{ "_type" : "account", "_id" : 1 }]
}// 路径中指定了索引和类型,通过ids数组指定多个id值
GET /{index}/{type}/_mget'
{"ids" : [ "2", "1" ]
}

_bulk

批量操作:将多个操作封装成一个操作,一次执行多个动作(create,index, update以及delete),并返回每个执行结果.
可以通过_bulk来执行批量插入、批量更新等操作

POST _bulk的请求主体的格式稍微有些不同:

{ action: { metadata }}\n
{ request body        }\n
{ action: { metadata }}\n
{ request body        }\n
...

它通过换行符(\n)连接到一起,最后一行也要有\n,每行一定要以换行符(\n)结尾, 包括最后一行 。这些换行符被用作一个标记,可以有效分隔行,这些行不能包含未转义的换行符,因为他们将会对解析造成干扰

  • action 必须是以下选项之一:

    • create:如果文档不存在,那么就创建它, 相当于 PUT /{index}/{type}/{id}/_create
    • index:创建一个新文档或者替换一个现有的文档, 相当于 PUT /{index}/{type}/{id}
    • update:部分更新一个文档, 即局部更新文档中的个别字段,相当于 /{index}/{type}/{id}/_update
    • delete:删除一个文档,删除操作不需要指定请求体,delete操作没有请求体,它紧接着另一个行为;记得最后一个换行符
  • metadata 每个动作需要的参数,json格式的,应该指定被索引、创建、更新或者删除的文档的_index,_type和 _id

每个子请求都是独立执行,因此某个子请求的失败不会对其他子请求的成功与否造成影响。 如果其中任何子请求失败,最顶层的 error 标志被设置为 true ,并且在相应的请求报告出错误明细
这也意味着 bulk 请求不是原子的: 不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求

POST /_bulk
{ "create": { "_index": "shop", "_type": "goods", "_id": 123 }}
{ "name":    "My first blog post" }
{ "index":  { "_index": "shop", "_type": "goods" }}
{ "name":    "My second blog post" }
{ "update": { "_index": "shop", "_type": "goods", "_id": 123, "retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
{ "delete": { "_index": "shop", "_type": "goods", "_id": 1234 }} 

我的微信公众号:

Elasticsearch入门教程(五):Elasticsearch查询(一)相关推荐

  1. ElasticSearch入门 第五篇:使用C#查询文档

    网址:http://www.cnblogs.com/ljhdo/p/4550135.html 这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Win ...

  2. python elasticsearch 入门教程(二) ---全文搜索

    python elasticsearch 入门教程(二) ---全文搜索 截止目前的搜索相对都很简单:单个姓名,通过年龄过滤.现在尝试下稍微高级点儿的全文搜索--一项 传统数据库确实很难搞定的任务. ...

  3. ElasticSearch入门教程-索引

    ElasticSearch入门教程-索引 在本节中,我们将向Elasticsearch添加一些索引,映射和数据.此数据将用于本教程中说明的示例中. 创建索引 PUT http://localhost: ...

  4. Scrapy爬虫入门教程五 Selectors(选择器)

    Scrapy爬虫入门教程一 安装和基本使用 Scrapy爬虫入门教程二 官方提供Demo Scrapy爬虫入门教程三 命令行工具介绍和示例 Scrapy爬虫入门教程四 Spider(爬虫) Scrap ...

  5. R语言七天入门教程五:认识并使用函数

    R语言七天入门教程五:认识并使用函数 一.什么是函数 在编程语言中,如果有一段代码需要在多次重复使用,除了复制粘贴外,还可以将其写成一个函数.函数可以很方便地实现代码复用,对于复杂的程序功能,可以将其 ...

  6. sql数据库教程百度云_绘画自学零基础入门教程|五天学会绘画pdf百度云下载!...

    绘画自学零基础入门教程|五天学会绘画pdf百度云下载!画画是可以让人留存记忆的事情.我自己就很喜欢画画来记录生活中一些特别的日子.场景还有我的家人朋友们.有时候,比照片更有故事感和纪念意义-有空拿出来 ...

  7. linux宝塔搭建网站,宝塔Linux面板搭建网站入门教程五(宝塔Linux面板安装WordPress博客程序)...

    本文于 2021-04-01 00:04 更新,本文內容具有時效性,如有失效,請在博客站內搜相關商家名稱,即可查看到關於此商家的最新優惠活動! 國外商家建議使用"谷歌瀏覽器"訪問, ...

  8. ElasticSearch实战系列五: ElasticSearch的聚合查询基础使用教程之度量(Metric)聚合

    Title:ElasticSearch实战系列四: ElasticSearch的聚合查询基础使用教程之度量(Metric)聚合 前言 在上上一篇中介绍了ElasticSearch实战系列三: Elas ...

  9. Elasticsearch系列-Elasticsearch入门教程

    引言 Elasticsearch是著名的开源分布式搜索和数据处理平台,是一个基于Lucene的分布式.实时.全文搜索系统,其稳定.可靠.高可用.可大规模扩展等特性,使得Elasticsearch的应用 ...

最新文章

  1. ubuntu系统初始化
  2. Linux学习之线程封装四:基于接口的封装
  3. python可以做什么开发-python适合做什么开发_python未来发展怎么样
  4. linux复制文件快捷键,Linux基础学习(基本命令和文件操作)
  5. CORS 跨域-同源策略
  6. Android QEMU 高速管道
  7. asp.net生命周期
  8. 再次“重新定义” 华为争做数据基础设施领航者
  9. 数据的统计分析与描述
  10. 经典的SharePoint 2010升级中的多核CPU冲突问题
  11. oracle索引大小暴增_Oracle创建索引前估算索引大小(dbms_space.create_index_cost)
  12. Codeforces Round #460 (Div. 2): E. Congruence Equation(枚举)
  13. php整数型转字符串,php如何将整数转为字符串
  14. 软件测试用例最简单最常见的模板和案例(QQ登陆,手机号,126邮箱)
  15. 简要罗列通过Allegro绘制的PCB封装步骤
  16. 输出大于某个正整数n的最小的质数
  17. 松翰单片机--SN8F5702学习笔记(四)ADC
  18. 【思维导图】前端开发JavaScript-巩固你的JavaScript知识体系
  19. xp打印机服务器属性修复,xp打印机服务器属性设置
  20. Genymotion 各对应版本

热门文章

  1. 升级Windows10,安装程序无法正常启动无法初始化工作目录
  2. Python 编程从入门到实践 6-7动手试一试 人
  3. 登陆163邮箱显示服务器验证失败是什么原因?微信怎么登陆邮箱?
  4. 做完近视手术应该注意什么?近视术后护理攻略请你收下
  5. 戴隐形眼镜好吗 隐形眼镜能经常戴吗
  6. 真正可以根治高度近视眼的方法(转载)
  7. 20多家银行加入“新加坡-香港”区块链贸易网络项目
  8. 梅姨一定想不到 中国人最爱的英国货竟然是一本童书
  9. VMware-vMotion简介和要求
  10. 向U盘中安装Linux系统的经验(不是制作安装盘)