简单搜索
在url后面加上_search关键字表示搜索请求,如:GET /megacorp/employee/_search
在?后面添加q的参数可以传入搜索参数,如:GET /megacorp/employee/_search?q=id:123
pretty关键字:在url请求后面加上?pretty(已经有问号时加&pretty),可以把响应结果格式化为 正常结构的json(没有加的话,会显示为string格式)。
/megacorp/employee/_search?q=id:123&pretty
如下:
响应结果:
{
"took" : 3, //搜索耗时,单位毫秒
"timed_out" : false, //是否超时
"_shards" : { //查询分片
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1, //总数
"max_score" : 3.3513753, //最大相关性得分
"hits" : [ { //查询结果
"_index" : "enlogistics", //所在索引
"_type" : "lg_line", //所属类别
"_id" : "582", //id
"_score" : 3.3513753, //当前数据的相关性得分
"_source" : { //查询内容
"id" : 582,
"lineType" : "120",
...
"global_ana_ch" : ",1700000000000186,HAMADA,RISDON,Dangerous"
}
} ]
}
}
结构化查询
一些复杂的查询无法直接通过url进行传参,它可以将参数以JSON格式放在request body中进行传递,由于GET请求不被广泛支持,所以也可以通过POST请求
通过一个简单的查询来了解:
GET /_search
{
"query": { // 表示结构化查询
"match": { // 查询方式,匹配查询
"tweet": "elasticsearch" // 字段名:查询内容
}
}
}
所有的查询请求url都必须以/_search结尾(?后面不算),结构化查询则都是以query为root key(后面介绍中的请求都是query里面的内容)
查询与过滤
查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异
- 一条过滤语句会询问每个文档的字段值是否包含着特定值
- 一条查询语句与过滤语句相似,不同的是查询语句会询问每个文档的字段值与特定值的匹配程度如何
总而言之,最主要的区别在于过滤的条件不影响相关度得分,查询的语句会影响相关度得分
另外,过滤语句会进行缓存,缓存过的过滤语句查询效率要远胜一条查询语句。所以除了需要计算相关度得分的,其它的都应该使用过滤语句。
过滤语句的关键字有:bool、term、terms、range、exists、missing等
查询语句的关键字有:bool、match_all、match、multi_match等,下面将一一介绍
bool过滤
bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
must :: 多个查询条件的完全匹配,相当于 and。
must_not :: 多个查询条件的相反匹配,相当于 not。
should :: 至少有一个查询条件匹配, 相当于 or。
这些参数可以分别继承一个过滤条件或者一个过滤条件的数组
{
"bool": {
"must": { "term": { "folder": "inbox" }},
"must_not": { "term": { "tag": "spam" }},
"should": [
{ "term": { "starred": true }},
{ "term": { "unread": true }}
]
}
}
term过滤
term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型)
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
terms过滤
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配
{
"terms": {
"tag": [ "search", "full_text", "nosql" ]
}
}
range过滤
range过滤允许我们按照指定范围查找一批数据
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
gt :: 大于
gte:: 大于等于
lt :: 小于
lte:: 小于等于
exists和missing过滤
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件
{
"exists": {
"field": "title"
}
}
match_all查询
使用match_all 可以查询到所有文档,是没有查询条件下的默认语句
{
"match_all": {}
}
match查询
match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符
{
"match": {
"tweet": "About Search"
}
}
如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将为你搜索你给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
提示: 做精确匹配搜索时,你最好用过滤语句(term),因为过滤语句可以缓存数据。
multi_match查询
multi_match查询允许你做match查询的的时候指定多个搜索字段
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
bool查询
bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是,bool 过滤可以直接给出是否匹配成功, 而bool 查询要计算每一个查询子句的 _score (相关性分值)。
must:: 查询指定文档一定要被包含。
must_not:: 查询指定文档一定不要被包含。
should:: 查询指定文档,有则可以为文档相关性加分。
以下查询将会找到 title 字段中包含 "how to make millions",并且 "tag" 字段没有被标为 spam。 如果有标识为 "starred" 或者发布日期为2014年之前,那么这些匹配的文档将比同类网站等级高
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
过滤查询
search API中只能包含 query 语句,所以我们需要用 filtered 来同时包含 "query" 和 "filter" 子句
{
"query": {
"filtered": {
"query": { "match": { "email": "business opportunity" }},//查询
"filter": { "term": { "folder": "inbox" }} //过滤
}
}
}
理解查询语句
想知道语句非法的具体错误信息,需要加上 explain 参数,类似sql的explain
GET /gb/tweet/_validate/query?explain
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}
获取搜索热度top5
get localhost:9200/top-terms/_search?pretty -d '{
"aggs": {
"top-terms-aggregation": {
"terms": { "field" : "text","size":5 }
}
}
}
模糊查询
http://192.168.1.52:9200/console/lg_line/_search
{
"query": {
"wildcard": {
"departureAll": {
"value": "*在迪士尼乐园,点亮心中奇梦。它是一个充满创造力、冒险精神与无穷精彩的快地。您可在此游览全球最大的迪士尼城堡——奇幻童话城堡,探索别具一格又令人难忘的六大主题园区——米奇大街、奇想花园、梦幻世界、探险岛、宝藏湾和明日世界,和米奇朋友在一起,感觉欢乐时光开业于2016年上海国际旅游度假区秀沿路亚朵酒店位于上海市浦东新区沪南公路(沪南公路与秀沿路交汇处),临近周浦万达广场、地铁11号线秀沿路站,距离上海南站、人民广场约20公里,距离迪线距*"
}
}
}
}
注意:模糊查询中通配符的解析存在bug,当通配符太多时解析非常耗费性能,甚至会拖垮整个ES服务,
因此应该把查询条件中的通配符替换掉(不让传入ES中)