【ES知识】ES基础查询语法

Elasticsearch是一个分布式的RESTful 风格的搜索和数据分析引擎。

 ES查询
下面介绍一下ES常用的几种查询

match查询
ES的查询有一个很大的特点就是分词。所以大家在使用ES的过程中脑子要始终有这么一个意识,你要查找的text是通过分词器分过词的,所以你去匹配的实际上是一个个被分词的片段。而你搜索的query也有可能会被分词,match就是一种会将你搜索的query进行分词的查询方法。我们结合例子来看!

比如我们要查询的索引结构如下:

{
    "_index": "text",
    "_id": "kIw57586Y",
    "_source": {
        "bookName": "This is a test",
        "author": "橙子",
        "num": 20
    }
}
_index代表索引名称,_id代表该条数据唯一id,_source代表该条数据具体的结构。

这里我们通过bookName字段来查询。

输入query语句如下:

GET http://ip:prot/text/_search
{
  "query": {
    "match": {
      "bookName":"test"
    }
  }
}
该条语句代表用match方式搜索索引为text中bookName可以匹配到test的语句。因为:

"bookName": "This is a test"
原文被分词器分词后包含test这个词语,所以可以正常被匹配出来。

这个例子比较简单,我们换个复杂一点的例子:

GET http://ip:prot/text/_search
{
  "query": {
    "match": {
      "bookName":"my test"
    }
  }
}

原因是match查询里,会对你查询的query也进行分词,也就是会将你的"my test"进行分词,得到my与test两个词语,然后用这两个词语分别去匹配文本,发现虽然my匹配不到,但是test可以匹配到,所以依然可以查出来。这个和我们传统的搜索方式确实存在差异,大家要注意。

那这种搜索方式存在的价值是什么呢?其实还有蛮大用处的。比如我们的ES库存储的是很多的英文好词好句,然后用户想提高自己的英文写作,因此想搜索出一些比较好的表达加在自己的文章中,那这个时候对于用户来讲,严格的匹配方式大概率什么都搜不到,但是像match这样的搜索方式便非常合适。例如有个好句是这样的:

If at first you don't succeed, try again.
然后用户用下面的方式搜索:

If you don't success
用match就可以很好的匹配出来。

2.2 match_phrase查询
既然match的限制比较小,那如果我们需要这个限制更强一点用什么方式呢?match_phrase便是一个比较不错的选择。match_phrase和match一样也是会对你的搜索query进行分词,但是,不同的是它不是匹配到某一处分词的结果就算是匹配成功了,而是需要query中所有的词都匹配到,而且相对顺序还要一致,而且默认还是连续的,如此一来,限制就更多了。我们还是举个例子。比如还是刚刚的索引数据:

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "橙子",
        "num": 20
    }
}
如果我们还用刚刚的方式搜索:

GET http://ip:prot/textbook/_search
{
  "query": {
    "match_phrase": {
      "bookName":"my test"
    }
  }
}
这次是匹配不到结果的。那么怎样才能匹配到结果呢?只能是搜索原文中的连续字串:

GET http://ip:prot/textbook/_search
{
  "query": {
    "match_phrase": {
      "bookName":"is a test"
    }
  }
}
这样是可以匹配到结果的。但是如此一来限制可能太大了一点,所以官方还给了一个核心餐宿可以调整搜索的严格程度,这个参数叫slop,我们举个例子:

GET http://ip:prot/textbook/_search
{
  "query": {
    "match_phrase": {
      "bookName":{
        "query":"is test",
        "slop":1
      }
    }
  }
}
比如我们将slop置为1,然后搜索"is test",虽然is test中间省略了一个词语"a",但是在slop为1的情况下是可以容忍你中间省略一个词语的,也可以搜索出来结果。以此类推,slop为2就可以省略两个词语了。大家可以根据自己的实际情况进行调整。

另外我们可以发现,如果在搜索时添加了辅助参数(比如slop)我们搜索格式的层级要往下扩展一层,之前的

"bookName":"my test"
要改为:

"bookName":{
    "query":"is test",
    "slop":1
}
我们注意一下就好了。

2.3 multi_match查询
有了前面的基础,multi_match比较好理解。实际上就是可以从多个字段中去寻找我们要查找的query:

GET http://ip:prot/textbook/_search
{
  "query": {
    "multi_match": {
        "query" : "橙子",
        "fields" : ["bookName", "author"]
    }
  }
}
比如这里我们是从bookName和author两个字段里去寻找老坛,虽然bookName没有,但是author可以匹配到,那也可以找到数据。所以本质上就是对bookName和author分别做了一次match:

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "橙子",
        "num": 20
    }
}
2.4 term查询
term查询也是比较常用的一种查询方式,它和match的唯一区别就是match需要对query进行分词,而term是不会进行分词的,它会直接拿query整体和原文进行匹配。所以不理解的小伙伴使用起来可能会非常奇怪:

GET http://ip:prot/textbook/_search
{
  "query": {
    "term": {
      "bookName": "This is a test doc"
    }
  }
}
当我们用这种方式进行搜索时,明明要搜索的和被搜索的文本一模一样,确就是搜不出来。这就是因为我们去搜的实际上并不是原文本身,而是被分词的原文,在原文被分好的每一个词语里,没有一个词语是:"This is a test doc",那自然是什么都搜不到了。所以在这种情况下就只能用某一个词进行搜索才可以搜到:

GET http://ip:prot/textbook/_search
{
  "query": {
    "term": {
      "bookName": "This"
    }
  }
}
2.5 terms查询
terms查询事实上就是多个term查询取一个交集,也就是要满足多个term查询条件匹配出来的结果才可以查到,所以是比单纯的term条件更为严格了:

GET http://ip:prot/textbook/_search
{
  "query": {
    "terms": {
      "bookName": ["This", "is"]
    }
  }
}
比如这个例子,是要求原文中既有This这个词,又有is这个词才可以被查到,那按照这个规则我们是可以匹配到数据的:

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "橙子",
        "num": 20
    }
}
但是如果改成了一个不存在的词便匹配不到了:

GET http://ip:prot/textbook/_search
{
  "query": {
    "terms": {
      "bookName": ["This", "my"]
    }
  }
}
2.6 fuzzy查询
fuzzy是ES里面的模糊搜索,它可以借助term查询来进行理解。fuzzy和term一样,也不会将query进行分词,但是不同的是它在进行匹配时可以容忍你的词语拼写有错误,至于容忍度如何,是根据参数fuzziness决定的。fuzziness默认是2,也就是在默认情况下,fuzzy查询容忍你有两个字符及以下的拼写错误。即如果你要匹配的词语为test,但是你的query是text,那也可以匹配到。这里无论是错写多写还是少写都是计算在内的。我们同样还是举例说明。

对于索引数据:

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "老坛",
        "num": 20
    }
}
如果查询语句为:

GET http://ip:prot/textbook/_search
{
  "query": {
    "fuzzy": {
      "bookName":"text"
    }
  }
}
这时肯定是用text来匹配原文中的每一个词,发现text和test最为接近,但是有一个字符的差异,在默认fuzziness为2的情况下,依然可以匹配出来。

当然这个fuzziness是可以调的,比如:

GET http://ip:prot/textbook/_search
{
  "query": {
    "fuzzy": {
      "bookName":{
        "value":"texts",
        "fuzziness":1
      }
    }
  }
}
在容忍度为1的情况下,如果你想查texts就查不到结果了。

2.7 range查询
range查询时对于某一个数值字段的大小范围查询,比如我这里特意所加的nums字段就是这个时候派上用场的。range的语法设计到了一些关键字:

gte:大于等于
gt:大于
lt:小于
lte:小于等于
GET http://ip:prot/textbook/_search

  "query": {
    "range": { 
      "num": { 
          "gte":20, 
          "lt":30 
      } 
    }
  } 
}
比如这样的条件就是去查找字段num大于等于20小于30的数据

那我们的数据便可以被查询到:

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "橙子",
        "num": 20
    }
}
2.8 bool查询
bool查询是上面查询的一个综合,它可以用多个上面的查询去组合出一个大的查询语句,它也有一些关键字:

must:代表且的关系,也就是必须要满足该条件
should:代表或的关系,代表符合该条件就可以被查出来
must_not:代表非的关系,也就是要求不能是符合该条件的数据才能被查出来
例如有这样一个查询:

GET http://ip:prot/textbook/_search
{
    "query":{
        "bool":{
            "must":{
                "match":{
                    "bookName":"橙子"
                }
            },
            "should":{
                "term":{
                    "author":"橙子"
                },
                "range":{
                    "num":{
                        "gt":20
                    }
                },
            }
        }
    }
}
这里就要求must里面的match是必须要符合的,但是should里面的两个条件就可以符合一条即可。

2.9 排序和分页
排序和分页也是建立在上述的那些搜索之上的。排序和分页的条件是和query平级去写的,我们一个一个来看。先举个例子:

GET http://ip:prot/textbook/_search
{
    "query":{
        "match":{
            "bookName":"橙子"
        }
    },
    "from":0,
    "size":100,
    "sort":{
        "num":{
            "order":"desc"
        }
    }
}
这里关于分页的语句是:

"from":0,
"size":100,
它代表的意思是按照页容量为100进行分页,取第一页​。

关于排序的语句是:

"sort":{
    "num":{
        "order":"desc"
    }
}
它需要指定一个字段,然后根据这个字段进行升序或降序。这里我们根据num来进行降序排序,如果想升序就把order的值改为asc就好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值