作者 | mr_xinchen
来源 | CSDN博客
出品 | CSDN(ID:CSDNnews)
Elasticsearch介绍
Elasticsearch是一款基于Lucene的分布式全文检索服务器,让我们看一下百度文库给出的解释。
用途:做搜索功能
使用案例:GitHub、维基百科、等等
Solr对比:
实时性ES高于Solr
Solr传统搜索性能高于ES
Elasticsearch安装
注意:安装必须在java1.8版本以上Windows环境
去官网下载获得压缩包一个,版本6.2.4
解压缩进入目录找到bin文件夹
双击运行bin文件夹中elasticsearch.bat脚本
在浏览器输入http://localhost:9200/
安装成功浏览器显示
Linux环境
1. 安装和配置
我们将在linux下安装Elasticsearch,使用版本6.2.4
2. 新建一个用户
出于安全考虑,elasticsearch默认不允许以root账号运行。
创建用户:
1useradd 用户名
设置密码:
-
1passwd 用户名
-
切换用户:
1su 用户名
3. 上传安装包,并解压
我们将安装包上传到:/home/用户名目录
解压缩:
1tar -zxvf elasticsearch-6.2.4.tar.gz
我们把目录重命名:
1mv elasticsearch-6.2.4/ elasticsearch
进入,查看目录结构:
1ls -l /home/用户名/elasticsearch
4. 修改配置
我们进入config目录:cd config
需要修改的配置文件有两个:
jvm.options
Elasticsearch基于Lucene的,而Lucene底层是java实现,因此我们需要配置jvm参数。
编辑jvm.options:
1vim jvm.options
默认配置如下:
-
1-Xms1g
-
2-Xmx1g
内存占用太多了,我们调小一些:
-
1-Xms512m
-
2-Xmx512m
elasticsearch.yml
1vim elasticsearch.yml
修改数据和日志目录:
-
1path.data: /home/用户名/elasticsearch/data
# 数据目录位置
-
2path.logs: /home/用户名/elasticsearch/logs
# 日志目录位置
我们把data和logs目录修改指向了elasticsearch的安装目录。但是这两个目录并不存在,因此我们需要创建出来。
进入elasticsearch的根目录,然后创建:
-
1mkdir data
-
2mkdir logs
修改绑定的ip:
1network.host: 0.0.0.0 # 绑定到0.0.0.0,允许任何ip来访问
默认只允许本机访问,修改为0.0.0.0后则可以远程访问
目前我们是做的单机安装,如果要做集群,只需要在这个配置文件中添加其它节点信息即可。
elasticsearch.yml的其它可配置信息:
5. 运行
进入elasticsearch/bin目录,可以看到下面的执行文件:
然后输入命令:
1./elasticsearch
发现报错了,启动失败:
错误1:内核过低
我们使用的是centos6,其linux内核版本为2.6。而Elasticsearch的插件要求至少3.5以上版本。不过没关系,我们禁用这个插件即可。
修改elasticsearch.yml文件,在最下面添加如下配置:
1bootstrap.system_call_filter: false
然后重启
错误2:文件权限不足
再次启动,又出错了:
1[1]: max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
我们用的是普通用户,而不是root,所以文件权限不足。
首先用root用户登录。
然后修改配置文件:
1vim /etc/security/limits.conf
添加下面的内容:
-
1* soft nofile
65536
-
2
-
3* hard nofile
131072
-
4
-
5* soft nproc
4096
-
6
-
7* hard nproc
4096
错误3:线程数不够
刚才报错中,还有一行:
1[1]: max number of threads [1024] for user [leyou] is too low, increase to at least [4096]
这是线程数不够。
继续修改配置:
-
1vim /etc/security/limits.d/
90-nproc.conf
-
修改下面的内容:
1* soft nproc 1024
改为:
1* soft nproc 4096
错误4:进程虚拟内存
1[3]: max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
vm.max_map_count:限制一个进程可以拥有的VMA(虚拟内存区域)的数量,继续修改配置文件, :
1vim /etc/sysctl.conf
添加下面内容:
1vm.max_map_count=655360
然后执行命令:
1sysctl -p
6. 重启终端窗口
所有错误修改完毕,一定要重启你的 Xshell终端,否则配置无效。
7. 启动
进入elasticsearch/bin目录,然后输入命令:
1./elasticsearch
可以看到绑定了两个端口:
9300:集群节点间通讯接口
9200:客户端访问接口
我们在浏览器中访问:http://127.0.0.1:9200
Elasticsearch理论知识
看过我上篇Lucene的文章,大家知道我把Lucene和传统数据库对比,其实他们很多相同之处,接下来我们拿Elasticsearch和Mysql进行比较。
-
1Mysql -> database -> table -> rows -> columns
-
2
-
3Elasticsearch -> index -> type -> documents -> fields
1. index(索引)
可以类似看成一个database,但区别于就是一个拥有几分相似特征的文档的集合,比如你可以有商品数据索引、或则客户数据索引。
2. type(类型)
可以类似看成一个table,就是给文档分分类用的,通常,会为具有一组共同字段的文档定义一个类型。
3. documents (文档)
可以类似看成一个table下一行数据, 一个文档是一个可被索引的基础信息单元。
4. fields(字段,在lucene中叫域)
可以类似看成一个table的字段,对文档数据根据不同属性进行的分类标识
5. mapping(映射)
可以类似看成字段的数据类型和约束,mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等
6. shards&replicas(分片&备份)
ES是分布式大数据量全文检索服务器,把文档数据切成片段,多个片合在一起是一个完整的数据。在分布式环境中很有就能出现单点故障问题,这时候需要备份每个片段会被复制和转移同步。
RESTfull语法
我这里使用kibana,也可以使用其他工具实现
1. 创建索引index和映射mapping
-
1PUT /索引名
-
2
-
3{
-
4
-
5
"mappings": {
-
6
-
7
"type名": {
-
8
-
9
"properties": {
-
10
-
11
"fields名": {
-
12
-
13
"type":
"类型",
-
14
-
15
"store": 是否储存[
true,
false],
-
16
-
17
"index": 是否索引[
true,
false],
-
18
-
19
"analyzer":
"分词器"
-
20
-
21 },
-
22
-
23
"fields名": {
-
24
-
25
"type":
"text",
-
26
-
27
"store":
true,
-
28
-
29
"index":
true,
-
30
-
31
"analyzer":
"standard"
-
32
-
33 }
-
34
-
35 }
-
36
-
37 }
-
38
-
39 }
-
40
-
41}
2. 创建索引index后添加映射mapping
-
1POST /索引名/type名/_mapping
-
2
-
3{
-
4
-
5
"type名":{
-
6
-
7
"properties":{
-
8
-
9
"fields名":{
-
10
-
11
"type":
"long",
-
12
-
13
"store":
true,
-
14
-
15
"index":
false
-
16
-
17 },
-
18
-
19
"fields名":{
-
20
-
21
"type":
"text",
-
22
-
23
"store":
true,
-
24
-
25
"index":
true,
-
26
-
27
"analyzer":
"standard"
-
28
-
29 }
-
30
-
31 }
-
32
-
33 }
-
34
-
35}
3. 删除索引index
1DELETE /索引名
4. 添加文档document
-
1POST /索引名/type名/[_id]
-
2
-
3{
-
4
-
5
"FIELD":
"VALUE",
-
6
-
7
"FIELD":
"VALUE",
-
8
-
9
"FIELD":
"VALUE"
-
10
-
11}
5. 修改文档document
-
1和添加相同,并且_id存在
-
-
6. 删除文档document
1DELETE /索引名/type名/_id
7. 根据_id查询
1GET /索引名/type名/_id
8. 根据term查询
-
1POST /索引名/type名/_search
-
2
-
3{
-
4
-
5
"query": {
-
6
-
7
"term": {
-
8
-
9
"FIELD":
"VALUE"
-
10
-
11 }
-
12
-
13 }
-
14
-
15}
9. 根据query_string查询
-
1POST /索引名/type名/_search
-
2
-
3{
-
4
-
5
"query": {
-
6
-
7
"query_string": {
-
8
-
9
"default_field":
"FIELD",
-
10
-
11
"query":
"this AND that OR thus"
-
12
-
13 }
-
14
-
15 }
-
16
-
17}
-
IK分词器
查看分词效果
-
1GET /_analyze
-
2
-
3{
-
4
-
5
"analyzer":
"standard",
-
6
-
7
"text":
"VALUE"
-
8
-
9}
集成IK分词器
下载IK分词器压缩包并解压缩
把其中elasticsearch文件夹改名ik-analyzer
把ik-analyzer文件夹放置在elasticsearch目录的plugins文件夹
重启elasticsearch服务器
测试分词器效果,把analyzer的值改成ik_smart 或 ik_max_word
Elasticsearch集群
这里ES集群相当简单,它不像solr需要一个注册中心,其实玩过分布式童鞋都知道,玩集群无非多开几个实例并用一个或多个注册中心管理起来。而ES集群模式使用一个 P2P类型(使用 gossip 协议)的分布式系统,说白了就是一个广播分布式系统。所以配置起来比外带注册中心简单。
1. cluster(集群)
一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。
2. node(节点)
就是一个集群的服务器
3. shards&replicas(分片&备份)
准备多台ES服务器,修改elasticsearch-cluster\config\elasticsearch.yml配置文件
-
1
#节点n的配置信息:
-
2
-
3
#集群名称,保证唯一
-
4
-
5cluster.name: elasticsearch
-
6
-
7
#节点名称,必须不一样
-
8
-
9node.name: node
-1
-
10
-
11
#必须为本机的ip地址
-
12
-
13network.host:
127.0
.0
.1
-
14
-
15
#服务端口号,在同一机器下必须不一样
-
16
-
17http.port:
9200
-
18
-
19
#集群间通信端口号,在同一机器下必须不一样
-
20
-
21transport.tcp.port:
9300
-
22
-
23
#设置集群自动发现机器ip集合
-
24
-
25discovery.zen.ping.unicast.hosts: [
"127.0.0.1:9300",
"127.0.0.1:9301",
"127.0.0.1:9302"]
-
JAVA客户端
7.1 创建Maven工程,导入坐标
-
1<dependencies>
-
2
-
3 <dependency>
-
4
-
5 <groupId>org.elasticsearch</groupId>
-
6
-
7 <artifactId>elasticsearch</artifactId>
-
8
-
9 <version>
5.6
.10</version>
-
10
-
11 </dependency>
-
12
-
13 <dependency>
-
14
-
15 <groupId>org.elasticsearch.client</groupId>
-
16
-
17 <artifactId>transport</artifactId>
-
18
-
19 <version>
5.6
.10</version>
-
20
-
21 </dependency>
-
22
-
23 <dependency>
-
24
-
25 <groupId>org.apache.logging.log4j</groupId>
-
26
-
27 <artifactId>log4j-to-slf4j</artifactId>
-
28
-
29 <version>
2.9
.1</version>
-
30
-
31 </dependency>
-
32
-
33 <dependency>
-
34
-
35 <groupId>org.slf4j</groupId>
-
36
-
37 <artifactId>slf4j-api</artifactId>
-
38
-
39 <version>
1.7
.24</version>
-
40
-
41 </dependency>
-
42
-
43 <dependency>
-
44
-
45 <groupId>org.slf4j</groupId>
-
46
-
47 <artifactId>slf4j-simple</artifactId>
-
48
-
49 <version>
1.7
.21</version>
-
50
-
51 </dependency>
-
52
-
53 <dependency>
-
54
-
55 <groupId>log4j</groupId>
-
56
-
57 <artifactId>log4j</artifactId>
-
58
-
59 <version>
1.2
.12</version>
-
60
-
61 </dependency>
-
62
-
63 <dependency>
-
64
-
65 <groupId>junit</groupId>
-
66
-
67 <artifactId>junit</artifactId>
-
68
-
69 <version>
4.12</version>
-
70
-
71 </dependency>
-
72
-
73</dependencies>
7.2 创建索引库
-
1
public
class ElasticsearchClient {
-
2
-
3 @Test
-
4
-
5
public void createIndex() throws
Exception {
-
6
-
7
// 创建settings对象
-
8
-
9 Settings settings = Settings.builder()
-
10
-
11 .put(
"cluster.name",
"elasticsearch")
-
12
-
13 .build();
-
14
-
15
// 创建客户端对象
-
16
-
17 TransportClient client =
new PreBuiltTransportClient(settings);
-
18
-
19 client.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(
"127.0.0.1"),
9300));
-
20
-
21
// 创建索引库
-
22
-
23 client.admin().indices().prepareCreate(
"index_hello").get();
-
24
-
25
// 关闭资源
-
26
-
27 client.close();
-
28
-
29 }
-
30
-
31}
7.3 设置映射
-
1
public
class ElasticsearchClient {
-
2
-
3 @Test
-
4
-
5
public void setMapping() throws
Exception {
-
6
-
7
// 创建settings对象
-
8
-
9 Settings settings = Settings.builder()
-
10
-
11 .put(
"cluster.name",
"elasticsearch")
-
12
-
13 .build();
-
14
-
15
// 创建客户端对象
-
16
-
17 TransportClient client =
new PreBuiltTransportClient(settings);
-
18
-
19 client.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(
"127.0.0.1"),
9300));
-
20
-
21
// 构建Mapping,RESTfull请求体
-
22
-
23 XContentBuilder builder = XContentFactory.jsonBuilder()
-
24
-
25 .startObject()
-
26
-
27 .startObject(
"article")
-
28
-
29 .startObject(
"properties")
-
30
-
31 .startObject(
"id")
-
32
-
33 .field(
"type",
"long")
-
34
-
35 .field(
"store",
true)
-
36
-
37 .endObject()
-
38
-
39 .startObject(
"title")
-
40
-
41 .field(
"type",
"text")
-
42
-
43 .field(
"store",
true)
-
44
-
45 .field(
"analyzer",
"ik_smart")
-
46
-
47 .endObject()
-
48
-
49 .startObject(
"content")
-
50
-
51 .field(
"type",
"text")
-
52
-
53 .field(
"store",
true)
-
54
-
55 .field(
"analyzer",
"ik_smart")
-
56
-
57 .endObject()
-
58
-
59 .endObject()
-
60
-
61 .endObject()
-
62
-
63 .endObject();
-
64
-
65
// 使用客户端把mapping设置到索引库
-
66
-
67 client.admin().indices()
-
68
-
69 .preparePutMapping(
"index_hello")
-
70
-
71 .setType(
"article")
-
72
-
73 .setSource(builder)
-
74
-
75 .get();
-
76
-
77
// 关闭资源
-
78
-
79 client.close();
-
80
-
81 }
-
82
-
83}
7.4 添加文档
-
1
public
class ElasticsearchClient {
-
2
-
3 @Test
-
4
-
5
public void addDocument() throws
Exception {
-
6
-
7
// 创建settings对象
-
8
-
9 Settings settings = Settings.builder()
-
10
-
11 .put(
"cluster.name",
"elasticsearch")
-
12
-
13 .build();
-
14
-
15
// 创建客户端对象
-
16
-
17 TransportClient client =
new PreBuiltTransportClient(settings);
-
18
-
19 client.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(
"127.0.0.1"),
9300));
-
20
-
21 XContentBuilder builder = XContentFactory.jsonBuilder()
-
22
-
23 .startObject()
-
24
-
25 .field(
"id",
1L)
-
26
-
27 .field(
"title",
"商务部:有序有力组织商贸企业复工复产")
-
28
-
29 .field(
"content",
"新华社北京2月23日电(记者陈炜伟、王雨萧)记者23日从商务部了解到,商务部印发《关于统筹做好生活必需品供应保障有关工作的通知》,要求各地商务主管部门在确保疫情防控安全的前提下,有序有力组织商贸企业复工复产。")
-
30
-
31 .endObject();
-
32
-
33
// 发送到服务器
-
34
-
35 client.prepareIndex(
"index_hello",
"article",
"1")
-
36
-
37 .setSource(builder)
-
38
-
39 .get();
-
40
-
41
// 关闭资源
-
42
-
43 client.close();
-
44
-
45
-
46
-
47 }
-
48
-
49}
7.5 查询(核心功能)
根据_Id查询
根据Term查询
根据QueryString查询
设置分页(在执行查询之前SearchResponse中方法setFrom和setSize)
设置高亮
-
1
public
class SearchIndex {
-
2
-
3
private TransportClient client;
-
4
-
5 @Before
-
6
-
7
public void init()throws
Exception {
-
8
-
9
// 创建settings对象
-
10
-
11 Settings settings = Settings.builder()
-
12
-
13 .put(
"cluster.name",
"elasticsearch")
-
14
-
15 .build();
-
16
-
17
// 创建客户端对象
-
18
-
19 client =
new PreBuiltTransportClient(settings);
-
20
-
21 client.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(
"127.0.0.1"),
9300));
-
22
-
23 }
-
24
-
25 @Test
-
26
-
27
public void searchById(){
-
28
-
29
// 创建查询对象
-
30
-
31 QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds(
"1",
"2");
-
32
-
33
// 执行查询
-
34
-
35 SearchResponse searchResponse = client.prepareSearch(
"index_hello")
-
36
-
37 .setTypes(
"article")
-
38
-
39 .setQuery(queryBuilder)
-
40
-
41 .get();
-
42
-
43
// 获取总记录数
-
44
-
45 SearchHits hits = searchResponse.getHits();
-
46
-
47 System.out.println(
"总记录数:"+hits.getTotalHits());
-
48
-
49
// 结果列表
-
50
-
51 Iterator<SearchHit> iterator = hits.iterator();
-
52
-
53
while (iterator.hasNext()){
-
54
-
55 SearchHit next = iterator.next();
-
56
-
57 Map<String, Object> source = next.getSource();
-
58
-
59 System.out.println(
"id:"+source.get(
"id"));
-
60
-
61 System.out.println(
"title:"+source.get(
"title"));
-
62
-
63 System.out.println(
"content:"+source.get(
"content"));
-
64
-
65 System.out.println(
"----------------------------------");
-
66
-
67 }
-
68
-
69
-
70
-
71 }
-
72
-
73 @Test
-
74
-
75
public void searchByTerm(){
-
76
-
77
// 创建查询对象
-
78
-
79 QueryBuilder queryBuilder = QueryBuilders.termQuery(
"title",
"复工");
-
80
-
81
// 执行查询
-
82
-
83 SearchResponse searchResponse = client.prepareSearch(
"index_hello")
-
84
-
85 .setTypes(
"article")
-
86
-
87 .setQuery(queryBuilder)
-
88
-
89 .get();
-
90
-
91
// 获取总记录数
-
92
-
93 SearchHits hits = searchResponse.getHits();
-
94
-
95 System.out.println(
"总记录数:"+hits.getTotalHits());
-
96
-
97
// 结果列表
-
98
-
99 Iterator<SearchHit> iterator = hits.iterator();
-
100
-
101
while (iterator.hasNext()){
-
102
-
103 SearchHit next = iterator.next();
-
104
-
105 Map<String, Object> source = next.getSource();
-
106
-
107 System.out.println(
"id:"+source.get(
"id"));
-
108
-
109 System.out.println(
"title:"+source.get(
"title"));
-
110
-
111 System.out.println(
"content:"+source.get(
"content"));
-
112
-
113 System.out.println(
"----------------------------------");
-
114
-
115 }
-
116
-
117
-
118
-
119 }
-
120
-
121 @Test
-
122
-
123
public void searchByQueryString(){
-
124
-
125
// 创建查询对象
-
126
-
127 QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(
"我家住在临安").defaultField(
"title");
-
128
-
129
// 执行查询
-
130
-
131 SearchResponse searchResponse = client.prepareSearch(
"index_hello")
-
132
-
133 .setTypes(
"article")
-
134
-
135 .setQuery(queryBuilder)
-
136
-
137 .setFrom(
0)
-
138
-
139 .setSize(
3)
-
140
-
141 .highlighter(
new HighlightBuilder().field(
"title").preTags(
"<em>").postTags(
"</em>"))
-
142
-
143 .get();
-
144
-
145
// 获取总记录数
-
146
-
147 SearchHits hits = searchResponse.getHits();
-
148
-
149 System.out.println(
"总记录数:"+hits.getTotalHits());
-
150
-
151
// 结果列表
-
152
-
153 Iterator<SearchHit> iterator = hits.iterator();
-
154
-
155
while (iterator.hasNext()){
-
156
-
157 SearchHit next = iterator.next();
-
158
-
159 Map<String, Object> source = next.getSource();
-
160
-
161 System.out.println(
"id:"+source.get(
"id"));
-
162
-
163 System.out.println(
"title:"+source.get(
"title"));
-
164
-
165 System.out.println(
"content:"+source.get(
"content"));
-
166
-
167 System.out.println(
"----------------------------------");
-
168
-
169 HighlightField title = next.getHighlightFields().get(
"title");
-
170
-
171 System.out.println(title.getFragments()[
0]);
-
172
-
173 }
-
174
-
175
-
176
-
177 }
-
178
-
179 @After
-
180
-
181
public void close(){
-
182
-
183 client.close();
-
184
-
185 }
-
186
-
187}
-
Spring Data Elasticsearch
使用原始JAVA客户端操作ES非常复杂,Spring最擅长做整合对ES的操作将会大大简化,所以还是推荐使用Spring Data,原生的作为了解即可。
8.1 创建Maven工程,导入坐标
-
1 <dependencies>
-
2
-
3 <dependency>
-
4
-
5 <groupId>org.elasticsearch</groupId>
-
6
-
7 <artifactId>elasticsearch</artifactId>
-
8
-
9 <version>
5.6
.10</version>
-
10
-
11 </dependency>
-
12
-
13 <dependency>
-
14
-
15 <groupId>org.elasticsearch.client</groupId>
-
16
-
17 <artifactId>transport</artifactId>
-
18
-
19 <version>
5.6
.10</version>
-
20
-
21 </dependency>
-
22
-
23 <dependency>
-
24
-
25 <groupId>org.apache.logging.log4j</groupId>
-
26
-
27 <artifactId>log4j-to-slf4j</artifactId>
-
28
-
29 <version>
2.9
.1</version>
-
30
-
31 </dependency>
-
32
-
33 <dependency>
-
34
-
35 <groupId>org.slf4j</groupId>
-
36
-
37 <artifactId>slf4j-api</artifactId>
-
38
-
39 <version>
1.7
.24</version>
-
40
-
41 </dependency>
-
42
-
43 <dependency>
-
44
-
45 <groupId>org.slf4j</groupId>
-
46
-
47 <artifactId>slf4j-simple</artifactId>
-
48
-
49 <version>
1.7
.21</version>
-
50
-
51 </dependency>
-
52
-
53 <dependency>
-
54
-
55 <groupId>log4j</groupId>
-
56
-
57 <artifactId>log4j</artifactId>
-
58
-
59 <version>
1.2
.12</version>
-
60
-
61 </dependency>
-
62
-
63 <dependency>
-
64
-
65 <groupId>junit</groupId>
-
66
-
67 <artifactId>junit</artifactId>
-
68
-
69 <version>
4.12</version>
-
70
-
71 </dependency>
-
72
-
73 <dependency>
-
74
-
75 <groupId>com.fasterxml.jackson.core</groupId>
-
76
-
77 <artifactId>jackson-core</artifactId>
-
78
-
79 <version>
2.8
.1</version>
-
80
-
81 </dependency>
-
82
-
83 <dependency>
-
84
-
85 <groupId>com.fasterxml.jackson.core</groupId>
-
86
-
87 <artifactId>jackson-databind</artifactId>
-
88
-
89 <version>
2.8
.1</version>
-
90
-
91 </dependency>
-
92
-
93 <dependency>
-
94
-
95 <groupId>com.fasterxml.jackson.core</groupId>
-
96
-
97 <artifactId>jackson-annotations</artifactId>
-
98
-
99 <version>
2.8
.1</version>
-
100
-
101 </dependency>
-
102
-
103 <dependency>
-
104
-
105 <groupId>org.springframework.data</groupId>
-
106
-
107 <artifactId>spring-data-elasticsearch</artifactId>
-
108
-
109 <version>
3.0
.9.RELEASE</version>
-
110
-
111 <exclusions>
-
112
-
113 <exclusion>
-
114
-
115 <groupId>org.elasticsearch.plugin</groupId>
-
116
-
117 <artifactId>transport-netty4-client</artifactId>
-
118
-
119 </exclusion>
-
120
-
121 </exclusions>
-
122
-
123 </dependency>
-
124
-
125 <dependency>
-
126
-
127 <groupId>org.springframework</groupId>
-
128
-
129 <artifactId>spring-test</artifactId>
-
130
-
131 <version>
5.0
.8.RELEASE</version>
-
132
-
133 <scope>test</scope>
-
134
-
135 </dependency>
-
136
-
137
-
138
-
139 </dependencies>
-
8.2 添加配置文件
-
1
<?xml version=
"1.0" encoding=
"UTF-8"
?>
-
2
-
3<beans xmlns=
"http://www.springframework.org/schema/beans"
-
4
-
5 xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
-
6
-
7 xmlns:context=
"http://www.springframework.org/schema/context"
-
8
-
9 xmlns:elasticsearch=
"http://www.springframework.org/schema/data/elasticsearch"
-
10
-
11 xsi:schemaLocation=
"
-
12
-
13http://www.springframework.org/schema/beans
-
14
-
15http://www.springframework.org/schema/beans/spring-beans.xsd
-
16
-
17http://www.springframework.org/schema/context
-
18
-
19http://www.springframework.org/schema/context/spring-context.xsd
-
20
-
21http://www.springframework.org/schema/data/elasticsearch
-
22
-
23http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
-
24
-
25">
-
26
-
27 <!-- 客户端对象 -->
-
28
-
29 <elasticsearch:transport-client id=
"esClient" cluster-name=
"elasticsearch" cluster-nodes=
"127.0.0.1:9300"/>
-
30
-
31 <!-- 包扫描器 -->
-
32
-
33 <elasticsearch:repositories base-package=
"com.itheima.es.repositories"/>
-
34
-
35 <!-- 模板对象 -->
-
36
-
37 <bean id=
"elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
-
38
-
39 <constructor-arg name="client" ref="esClient"/>
-
40
-
41 </bean>
-
42
-
43</beans>
-
8.3 创建实体类,添加dao接口
-
1@Document(indexName =
"my_blog",type =
"article")
-
2
-
3
public
class Article {
-
4
-
5 @Id
-
6
-
7 @Field(type = FieldType.Long)
-
8
-
9
private Long id;
-
10
-
11 @Field(type = FieldType.Text,analyzer =
"ik_smart")
-
12
-
13
private String title;
-
14
-
15 @Field(type = FieldType.Text,analyzer =
"ik_smart")
-
16
-
17
private String content;
-
18
-
19
-
20
-
21
public Article() {
-
22
-
23 }
-
24
-
25
-
26
-
27
public Article(Long id, String title, String content) {
-
28
-
29 this.id = id;
-
30
-
31 this.title = title;
-
32
-
33 this.content = content;
-
34
-
35 }
-
36
-
37
-
38
-
39
public Long getId() {
-
40
-
41
return id;
-
42
-
43 }
-
44
-
45
-
46
-
47
public void setId(Long id) {
-
48
-
49 this.id = id;
-
50
-
51 }
-
52
-
53
-
54
-
55
public String getTitle() {
-
56
-
57
return title;
-
58
-
59 }
-
60
-
61
-
62
-
63
public void setTitle(String title) {
-
64
-
65 this.title = title;
-
66
-
67 }
-
68
-
69
-
70
-
71
public String getContent() {
-
72
-
73
return content;
-
74
-
75 }
-
76
-
77
-
78
-
79
public void setContent(String content) {
-
80
-
81 this.content = content;
-
82
-
83 }
-
84
-
85
-
86
-
87 @Override
-
88
-
89
public String toString() {
-
90
-
91
return
"Article{" +
-
92
-
93
"id=" + id +
-
94
-
95
", title='" + title +
'\'' +
-
96
-
97
", content='" + content +
'\'' +
-
98
-
99
'}';
-
100
-
101 }
-
102
-
103}
-
1
public
interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
-
2
-
3}
8.4 索引映射和文档增删改查
-
1@RunWith(SpringRunner.class)
-
2
-
3@ContextConfiguration(
"classpath:applicationContext.xml")
-
4
-
5
public
class ESTest {
-
6
-
7 @Autowired
-
8
-
9
private ArticleRepository articleRepository;
-
10
-
11 @Autowired
-
12
-
13
private ElasticsearchTemplate template;
-
14
-
15 @Test
-
16
-
17
public void createIndex(){
-
18
-
19
// 创建索引并配置映射关系
-
20
-
21 template.createIndex(Article.class);
-
22
-
23
// 配置映射
-
24
-
25
// template.putMapping(Article.class);
-
26
-
27 }
-
28
-
29 @Test
-
30
-
31
public void addDocumentAndUpdateDocument(){
-
32
-
33 Article article =
new Article(
2L,
"时政新闻眼丨在一场罕见的电视电话会上,习近平这样动员战“疫”",
"2月23日,农历二月初一。一场特别的会议在人民大会堂召开,分会场一直设到了县、团。中国正在打一场疫情防控的人民战争、总体战、阻击战。怎样分析这场战争?目前打到了哪一步?如何全面打赢?亲自指挥这场战争的习近平在这场“战时会议”上从容作答。");
-
34
-
35
// 添加文档
-
36
-
37 articleRepository.save(article);
-
38
-
39 }
-
40
-
41 @Test
-
42
-
43
public void delDocument(){
-
44
-
45
// 根据Id删除
-
46
-
47 articleRepository.deleteById(
1L);
-
48
-
49
// 全部删除
-
50
-
51
// articleRepository.deleteAll();
-
52
-
53 }
-
54
-
55 @Test
-
56
-
57
public void findAll(){
-
58
-
59 Iterable<Article> all = articleRepository.findAll();
-
60
-
61 all.
forEach(a-> System.out.println(a));
-
62
-
63 }
-
64
-
65 @Test
-
66
-
67
public void findById(){
-
68
-
69 Optional<Article> optional = articleRepository.findById(
2L);
-
70
-
71 System.out.println(optional.get());
-
72
-
73 }
-
74
-
75}
8.5 自定义查询
在接口中定义自定义查询,使用IDEA会有提示这里就不做介绍
8.6 原始查询条件查询
-
1 @Test
-
2
-
3
public void nativeSearch(){
-
4
-
5 NativeSearchQuery query =
new NativeSearchQueryBuilder()
-
6
-
7 .withQuery(
-
8
-
9 QueryBuilders.queryStringQuery(
"测试一个查询")
-
10
-
11 .defaultField(
"title")
-
12
-
13 ).withPageable(PageRequest.of(
0,
15))
-
14
-
15 .build();
-
16
-
17 AggregatedPage<Article> articles = template.queryForPage(query, Article.class);
-
18
-
19 articles.
forEach(a-> System.out.println(a));
-
20
-
21 }
到此ES学习已经够项目上使用了,所以学了这门技术就不要让他在你的大脑吃灰,赶紧应用到你们的项目中,最后祝大家技术越学越NB!
附 字段属性
字段属性详解
type
Elasticsearch中支持的数据类型非常丰富:
我们说几个关键的:
String类型,又分两种:
text:可分词,不可参与聚合
keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
Numerical:数值类型,分两类
基本数据类型:long、interger、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float
需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
Date:日期类型
elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
index
index影响字段的索引情况。
true:字段会被索引,则可以用来进行搜索。默认值就是true
false:字段不会被索引,不能用来搜索
index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。
但是有些字段是我们不希望被索引的,比如商品的图片信息,就需要手动设置index为false。
store
是否将数据进行额外存储。
在学习lucene和solr时,我们知道如果一个字段的store设置为false,那么在文档列表中就不会有这个字段的值,用户的搜索结果中不会显示出来。
但是在Elasticsearch中,即便store设置为false,也可以搜索到结果。
原因是Elasticsearch在创建文档索引时,会将文档中的原始数据备份,保存到一个叫做_source的属性中。而且我们可以通过过滤_source来选择哪些要显示,哪些不显示。
而如果设置store为true,就会在_source以外额外存储一份数据,多余,因此一般我们都会将store设置为false,事实上,store的默认值就是false。
boost
激励因子,这个与lucene中一样
其它的不再一一讲解,用的不多,大家参考官方文档:
原文链接:
https://blog.csdn.net/mr_xinchen/article/details/104231377
【End】
在全民抗疫的特殊时期下,在人员复杂、流动量大地方的出入口处都设置了无接触式无感红外人体测温系统。
在这次疫情防控中,无感人体测温系统发挥了怎样的作用?高精准的无感人体测温系统的核心技术武器是什么?对于开发者们来说,大家应该了解哪些技术?
今晚7点《多场景疫情防控:解读云边端联动下的全栈 AI 技术应用》
推荐阅读
☞微信回应钉钉健康码无法访问;谷歌取消年度 I/O 开发者大会;微软公布 Visual Studio 最新路线图 | 极客头条
☞6个步骤,告诉你如何用树莓派和机器学习DIY一个车牌识别器!(附详细分析)
☞什么是 CD 管道?一文告诉你如何借助Kubernetes、Ansible和Jenkins创建CD管道!
你点的每一个在看,我认真当成了喜欢
转载:https://blog.csdn.net/csdnnews/article/details/104666931