Elasticsearch是一个分布式的RESTful 风格的搜索和数据分析引擎,它使用方便,查询速度快,因此也被越来越多的开发人员使用。

本篇文章主要带大家过一下ES的基础查询语法,但对于其背后的原理和查询机理我不会做太多介绍,好了我们开始正题。

1. ES分词器

在学习查询语法之前有必要带大家了解一下ES的分词器。因为这是题主认为ES搜索引擎最大的特点了,它查询速度之所以这么快也和这个有很大关系。但更重要的是,如果我们不了解ES会对你存储的索引文本或者查询query进行分词,后面的语法你将很难理解。

对于我们存入ES索引(Index)中的各个字段(Term),ES内部都会有一个分词器对其进行分词,然后将这个分词结果存储起来,方便你未来的查询使用,这个分词器我们也可以直接很方便的调用,只要访问其_analyze即可:

 POST http://ip:prot/_analyze
{
  "analyzer": "standard",
  "text": "This is a test doc"
}

这里需要指定一个分词器,ES默认的分词器是standard,不过只支持英文分词,如果你用它来对中文进行分词的话会直接按字拆分,有一些中文分词器可以下载使用,像ik或者jieba之类的,这里便不去介绍如何安装了,感兴趣的可以查阅相关文章。

回到正题,我们用上述的分词请求返回的结果如下:

{
	"tokens": [
		{
			"token": "this",
			"start_offset": 0,
			"end_offset": 4,
			"type": "<ALPHANUM>",
			"position": 0
		},
		{
			"token": "is",
			"start_offset": 5,
			"end_offset": 7,
			"type": "<ALPHANUM>",
			"position": 1
		},
		{
			"token": "a",
			"start_offset": 8,
			"end_offset": 9,
			"type": "<ALPHANUM>",
			"position": 2
		},
		{
			"token": "test",
			"start_offset": 10,
			"end_offset": 14,
			"type": "<ALPHANUM>",
			"position": 3
		},
		{
			"token": "doc",
			"start_offset": 15,
			"end_offset": 18,
			"type": "<ALPHANUM>",
			"position": 4
		}
	]
}

可以看到我们的句子就被分词器这样做好了分词,还有偏移量之类的信息。

这里只是带大家看一下ES是如何做到分词的,我们平时查询的话自己是用不到分词的,这些分词都是在保存索引时ES自动分好存储起来的。


2. ES查询

下面介绍一下ES常用的几种查询(题主只介绍常用的,一些复杂用法可能不会都介绍全,大家在实际学习和工作中遇到了再去官方文档中查就好啦)。

2.1 match查询

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

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

{
    "_index": "textbook",
    "_id": "kIwXeYQB8iTYJNkI986Y",
    "_source": {
        "bookName": "This is a test doc",
        "author": "老坛",
        "num": 20
    }
}

_index代表索引名称,_id代表该条数据唯一id,_source代表该条数据具体的结构。

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

输入query语句如下:

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

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

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

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

大家认为这个能否被匹配出来呢?

原文中根本就没有my这个词语,那怎么被匹配出来?但实际上是可以匹配出来的。

原因是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就可以很好的匹配出来。