文章字数:1511,阅读全文大约需要6分钟
ElasticSearch
是一款使用java开发基于Lucene
的开箱即用的全文搜索引擎。使用REST API
操作接口。整理自阮一峰的教程
安装
Java8
环境安装
ElasticSearch-5.5.1
1
2
3
4
5
6# 下载压缩包到当前目录
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip
# 解压缩
$ unzip elasticsearch-5.5.1.zip
# 进入目录
$ cd elasticsearch-5.5.1/中文分词插件
ik
1
2
3# 使用elastic插件工具下载安装插件
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.1/elasticsearch-analysis-ik-5.5.1.zip
# 重启Elastic即可安装
开始使用
启动
1
./bin/elasticsearch
解决
max virtual memory areas vm.maxmapcount [65530] is too low
1
$ sudo sysctl -w vm.max_map_count=262144
查看信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 默认9200端口运行
$ curl localhost:9200
{
"name" : "atntrTf",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "tf9250XhQ6ee4h7YI11anA",
"version" : {
"number" : "5.5.1",
"build_hash" : "19c13d0",
"build_date" : "2017-07-18T20:44:24.823Z",
"build_snapshot" : false,
"lucene_version" : "6.6.0"
},
"tagline" : "You Know, for Search"
}允许非本机访问
修改config/elasticsearch.yml
去除network.host
注释,修改值1
2
3
4# 任何人都能访问(不推荐)
network.host: 0.0.0.0
# 指定ip
network.host: 192.168.1.1
基本概念
cluster
集群,多个Elastic
实例组成一个集群cluster
。实例可以运行在多个/同一个服务器上。Node
节点,一个Elastic
实例就是一个节点。一组节点构成一个集群。Index
索引,查找数据的顶层单位。Elastic
会索引所有字段,经过处理后写入一个反向索引Inverted Index
。Index
可以理解成单个数据库。Index
名字必须是小写Document
文档,Index
里的单条记录成为Document
文档。许多文档构成了Index
。文档是json类型表示,可以理解为一个json对象。1
2
3
4
5{
"title":"Elastic分布式全文搜索引擎",
"keyword":"java,search",
"body":"这是内容"
}- 同一个文档
(Doucment)
最好结构(scheme)
相同* Type
分组、类型,Document
可以进行分组。根据虚拟逻辑进行分组,比如技术博问和散文博文,用来过滤Documeent
。根据规划,Elastic6 版本之循序Index中包好一个Type, 7版本将移除type。
操作
新建
Index
1
2# 发送PUT请求创建Index
curl -X PUT 'localhost:9200/weather'服务器返回
1
2
3
4
5# acknowledged表示操作成功
{
"acknowledged":true,
"shards_acknowledged":true
}删除
Index
1
2# 发送DELETE请求删除
curl -X DELETE 'localhost:9200/weather'设置
Index
详细内容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 创建叫accounts的Index
curl -X PUT 'localhost:9200/accounts' -d '
{
"mappings":{
// 有一个type叫person
"TypePerson":{
"properties":{
//字段1 User
"user":{
"type":"text",//文本类型
"analyzer":"ik_max_word",//字段分词器使用ik提供的文本最大数量分词。
"search_analyzer":"ik_max_word"//搜索分词器
},
//字段2 Title
"title":{
...同上
}
}
}
}
}'新增记录(指定id)
1
2
3
4
5
6
7# 向accounts的person分组插入(PUT)
# 1为此记录的id,任意字符。
$ curl -X PUT 'localhost:9200/accounts/person/1' -d '
{
"user": "张三",
"title": "工程师"
}'返回
1
2
3
4
5
6
7
8
9{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{"total":2,"successful":1,"failed":0},
"created":true
}新增记录(不指定id)
1
2
3
4
5
6
7# 使用POST,服务器随机生成字符串形式的id
$ curl -X POST 'localhost:9200/accounts/person' -d '
{
"user": "李四",
"title": "工程师",
"desc": "系统管理"
}'如果没有创建Index直接插入会自动生成指定的Index。
查看记录
1
2# 使用GET `Index/Type/Id`查看,pretty表示以易读格式返回。
$ curl 'localhost:9200/accounts/person/1?pretty=true'返回
1
2
3
4
5
6
7
8
9
10
11
12{
"_index" : "accounts",
"_type" : "person",
"_id" : "1",
"_version" : 1,
"found" : true,//没找到 false
"_source" : {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理"
}
}删除记录
1
2# delete id
curl -X DELETE 'localhost:9200/accounts/person/1'更新记录
1
2
3# 重新发送一次就可以了
curl -X PUT 'localhost:9200/accounts/person/1' -d
'...'返回
1
2
3"_version" : 2,//版本+1
"result" : "updated",//结果从创建变成修改
"created" : false//created 变成 false查询所有数据
1
2# GET请求直接访问
$ curl 'localhost:9200/accounts/person/_search'返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33{
"took":2,
"timed_out":false,
"_shards":{"total":5,"successful":5,"failed":0},
"hits":{
"total":2,
"max_score":1.0,
"hits":[
{
"_index":"accounts",
"_type":"person",
"_id":"AV3qGfrC6jMbsbXb6k1p",
"_score":1.0,
"_source": {
"user": "李四",
"title": "工程师",
"desc": "系统管理"
}
},
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_score":1.0,
"_source": {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理,软件开发"
}
}
]
}
}took
操作耗时(毫秒)、timed_out
是否超时、hits
命中的记录hits
字段含义1
2
3
4total:返回记录数,本例是2条。
max_score:最高的匹配程度,本例是1.0。
hits:返回的记录组成的数组。
hits下_score表示匹配的程序,按照这个字段排序的全文搜索
1
2
3
4
5# 查询desc字段中包含软件这个词的
$ curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "软件" }}
}'指定全文搜索结果条数
1
2
3
4
5
6# size 1 指定返回一条结果
$ curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "管理" }},
"size": 1
}'位移/跳过指定数量的结果
1
2
3
4
5
6$ curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "管理" }},
"from": 1,//跳过1条
"size": 1
}'条件或、条件且
或1
2
3
4
5# 软件或是系统
$ curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "软件 系统" }}
}'且
1
2
3
4
5
6
7
8
9
10
11
12# desc 拥有软件关键词同时也要拥有系统关键词
$ curl 'localhost:9200/accounts/person/_search' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "desc": "软件" } },
{ "match": { "desc": "系统" } }
]
}
}
}'后台运行
linux
通用方法1
2
3
4
5
6
7# nohup表示不依赖终端,可以在同一个终端继续其他事情
# &不依赖于用户
nohup bin/elasticsearch &
# 查看日志
tail -fn 200 nohup.out
# 重定向输出信息 >/dev/null->将所有正确输出都保存到null文件中(抛弃) 2>&1 ->2即错误信息,重定向到1(正确信息中)
nohup bin/elasticsearch >/dev/null 2>&1 &Elastic
参数1
2# -d 代表后台运行
bin/elasticsearch -d关闭后台程序
1
2
3
4# 查找进程
ps -ef|grep elastic
# 杀死进程
kill 41496
模糊查询+分页
1 | Page<User> findByUsernameContainingOrderByCreateTimeDesc(String username,Pageable pageable); |
调用
1 | Pageable page = PageRequest.of(0 , 2); |
优化
Elastic
数据存储在磁盘中,查询的时候会自动提取到Filesystem Cache
中。增加Filesystem Cache
(内存)的容量,以及预知会有大量访问的数据自己提前定时查询,使其写入内存。热数据冷数据分离,热数据不会被冷数据挤下去。- join/nested/parent-child 这些操作尽量不要做
- 分页默认的性能很低,越往深层越慢。使用 Scroll API,滚动刷新(不能跳页)
- 配合其他数据库使用,es查询会查询所有数据,但是大部分可能没用。可以将需要检索的字段和id存入ES,再用id在mysql/HBase中取出其他的。