如何安装及使用Elastic Search

最近产品需要一个搜索商城中的商品的功能,于是接触了一下Elastic Search。虽然久仰它的大名,但一直都没有真正用过。这次稍微摸索了一下,顺便记录下来,说不定哪天就真的需要用上了。

安装

首先需要下载Elastic Search,我选择了.zip格式的安装包,下载地址在这里。下载完成后就拿到了一个5.2.2版本的Elastic Search的安装包,只需要解压即可使用。因为我喜欢把软件安装到主目录的app目录下,所以我用的命令是

1
2
cd /home/liutos/app
unzip ../installer/elasticsearch-5.2.2.zip

主目录下的installer是我习惯的用来存放软件的安装包的位置。解压后生成了一个名为elasticsearch-5.2.2的新目录。在这个目录下有一个名为bin的子目录,只需要进入该目录运行其中的elasticsearch文件即可,实例命令为

1
2
cd elasticsearch-5.2.2/bin
./elasticsearch -d

为了让Elastic Search可以不占用当前的终端,添加了-d选项,使其以后台进程(daemon)的方式运行。Elastic Search需要JVM才能运行,在执行上面的命令之前请各位自行准备好Java程序的运行环境。成功启动后,Elastic Search默认会监听9200端口,可以通过浏览器访问http://localhost:9200来确认Elastic Search是否正常启动了

使用

创建索引

遵照官方文档中的指导,先创建一个索引以便后续向这个索引中添加文档。假设要创建的索引是为商品准备的,取名为products,可以通过如下的命令创建出来

1
curl -X PUT 'http://localhost:9200/products'

创建成功后Elastic Search的响应结果为

1
{"acknowledged":true,"shards_acknowledged":true}

如果希望Elastic Search返回更可读的形式,可以添加?pretty参数到上面的URL的末尾。

文档的增删查改

索引已经创建了,就可以创建文档了。Elastic Search的文档是对象形式的,假设现在要创建的对象的类型为product,示例命令如下

1
2
3
4
5
curl -X POST 'http://localhost:9200/products/product' --data '
{
"id": 1,
"name": "Product 1"
}'

在我的机器上,Elastic Search的响应结果为

1
{"_index":"products","_type":"product","_id":"AVqpZHmVckriR6iVcbaW","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"created":true}

其中名为”_id”的字段的值为Elastic Search自动为这份新写入的文档分配的ID,通过这个ID可以从Elastic Search中取出这份文档,示例命令如下

1
curl 'http://localhost:9200/products/product/AVqpZHmVckriR6iVcbaW?pretty'

相当的RESTful的接口路径,也许你已经猜到了,删除一个文档的代码就是将请求的GET方法替换为DELETE。是的,示例代码如下

1
curl -X DELETE 'http://localhost:9200/products/product/AVqpZHmVckriR6iVcbaW?pretty'

再次查找刚才的ID的文档时,响应结果中的”_found”字段的值就已经变成了false了。关于修改文档的方法,请参考官方手册中的章节

搜索

准备数据

最简单的搜索接口的使用就是通过浏览器访问http://localhost:9200/products/_search这个地址了。在我的机器上,看到的页面内容为如下的JSON字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{

"took": 42,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": [ ]
}

}

为了方便接下来的演示,先通过Elastic Search的_bulk接口向其批量创建文档数据,示例代码如下

1
curl -X POST 'http://localhost:9200/_bulk?pretty' --data-binary '@docs'

其中docs文件中的内容为

1
2
3
4
5
6
7
8
{"create": {"_index": "products", "_type": "product", "_id": 1}}
{"name": "设计模式之禅"}
{"create": {"_index": "products", "_type": "product", "_id": 2}}
{"name": "失控:全人类的最终命运和结局"}
{"create": {"_index": "products", "_type": "product", "_id": 3}}
{"name": "构建高性能Web站点", "price": 75.00, "author": "郭欣"}
{"create": {"_index": "products", "_type": "product", "_id": 4}}
{"name": "大型网站技术架构:核心原理与案例分析", "price": 59.00, "author": "李智慧", "publisher": "电子工业出版社"}

尽管这里是一个文本文件,但是根据官方文档的说法,此处需要使用curl的二进制模式来发送数据,否则会报错。

个性化搜索

如果希望找到《失控》这本书的信息,那么可以根据书名进行查找,示例代码如下

1
curl 'http://localhost:9200/products/_search?q=name:失控'

Elastic Search提供了许多的搜索选项,如果全部通过URL中的query string来传递将会非常难以构造。为此,可以使用Elastic Search提供的基于HTTP body的参数传递方式,示例代码如下

1
curl -X GET 'http://localhost:9200/products/_search' --data '{"query": {"match": {"name": "失控"}}}'

Elastic Search支持相当丰富的搜索选项,这里不逐一介绍了,大家可以从官方文档的这里开始翻看。本来想在Chrome的POSTMAN插件中试验搜索功能的,结果当我选定了GET方法后,就不需要我提交HTTP body了,因此还是用curl进行演示。回到正题,如果我们搜索的是一个“站”字,那么Elastic Search会吐出两个结果,此处可以使用搜索接口的fromsize参数,分别控制返回的内容取自搜索结果中的哪一个片段。例如想要取出结果中的第二个,可以使用下列代码

1
curl -X GET 'http://localhost:9200/products/_search?pretty' --data '{"from": 1, "size": 1, "query": {"match": {"name": "站"}}}'

通过结合使用fromsize参数,可以实现许多应用中所要求的分页功能。在我厂的业务场景中,商品信息还是很多的,不可能全部放入到Elastic Search中作为文档数据存储,Elastic Search只是负责提供搜索出来的商品ID即可,之后再通过商品ID从原来的商品的数据库中按照顺序取出对应的完整的商品信息。因此,在搜索Elastic Search时实际上只需要商品的ID就足够了,可以通过Elastic Search提供的_source字段控制接口吐出的内容,示例代码如下

1
curl -X GET 'http://localhost:9200/products/_search?pretty' --data '{"query": {"match_all": {}}, "_source": ["_id"]}'

这样在吐出的内容中_source字段的值就会是一个空对象,应用程序只需要取每一个hits数组中的记录的”_id”字段即可。这样做的目的是减少Elastic Search通过网络传输了一部分毫无必要的数据,略微优化一下网络开销

全文完