文章目录
Spring整合Elasticsearch
引入依赖
- spring-boot-starter-data-elasticsearch
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置Elasticsearch
- cluster-name集群名
- cluster-nodes集群节点
# ElasticsearchProperties
# 配置集群名,与es配置文件中的一致
spring.data.elasticsearch.cluster-name=nowcoder
# 集群节点,格式 节点ip地址:端口
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
解决冲突
如果项目中使用了redis,则需要解决冲突
es和redis都基于netty,这两者在启动netty时,会产生冲突:系统会认为redis已经启动了netty,es无法再启动
要尽可能在服务启动早期的时候,修改es.set.netty.runtime.available.processors为 false
修改入口类,因为入口类是最先被加载的
@PostConstruct: 管理bean的生命周期,主要用于初始化的方法,该注解修饰的方法在构造器调用完以后被执行
在这个初始化方法中修改系统属性就足够早
@SpringBootApplication
public class CommunityApplication {
@PostConstruct
public void init() {
// 解决netty启动冲突问题
// es.set.netty.runtime.available.processors 从 Netty4Utils.setAvailableProcessors() 中找到
// 设置系统属性
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
public static void main(String[] args) {
SpringApplication.run(CommunityApplication.class, args);
}
}
使用Elasticsearch
Spring Data Elasticsearch
用于访问es服务器的API
-
ElasticsearchTemplate :有特殊情况,DiscussPostRepository处理不了时使用
-
ElasticsearchRepository: 接口,需要定义一个子接口继承他,声明访问哪些数据,Spring会自动实现这个接口
所有的代码都是Spring自动生成的,Spring会自动将实体数据和es服务器的索引进行映射,因此需要用注解
代码实例:
// es可以看成特殊的数据库,因此加上注解@Repository // @Mapper是MyBa'ti'd专有注解 // @Repository是spring提供的,针对数据访问层的注解 @Repository // es的接口一般取名XXXRepository,该接口访问的是帖子,故叫DiscussPostRepository public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost, Integer> { // 继承时要用泛型声明:当前接口要处理的实体类,以及实体类中的id类型 // 父接口ElasticsearchRepository中 已经定义好了对es服务器访问的增删改查方法 // 声明完泛型,加上注解之后,spring会自动实现自定义的子接口DiscussPostRepository }
建立映射关系
要对spring说明哪个实体类和es的索引怎样进行对应,建立映射关系,映射完成后,spring底层就可以帮我们生成实现类
-
用@Document指明 表 和 es 中索引的对应关系
@Document ( indexName = “…”, type = “…”, shards = , replicas = )
indexName: 实体数据映射到哪个索引上。通常为全小写的类名
type: 实体数据映射到哪个类型上。类型已经在逐步被弱化甚至取消了,因此写成固定的 _doc
shards: 创建几个分片。根据服务器处理能力配
replicas: 创建几个副本。
没有指定索引会创建这个索引,并且是根据指定分片和副本进行创建的 -
指明 实体中属性 和 es中字段 的对应关系
给类中每个 属性 上加注解用于和 索引中的字段 相关联
表的id属性要 加 @id 注解
@Id // 与索引中id字段对应
private int id;
其他普通属性 加 @Field注解并指明字段类型
// 用于普通字段,需指明字段类型
@Field(type = FieldType.Integer)
private int userId;
当某些属性 对应的 es字段要用于关键词匹配时,需在注解中指明使用的analyzer和searchAnalyzer
analyzer为存储时候的解析器/分词器。
当我们存一句话时,会提取出关键词,并用关键词关联这句话,搜索时就可以通过关键词搜到这句话
因此存的时候,因该尽可能将一句话拆出尽可能多的关键词,以扩大搜索范围。
故需要一个范围非常大的分词器,而我们安装的中文分词器中存在这样的分词器——ik_max_word
searchAnalyzer为搜索时候解析器/分词器
搜索时,输入的句子不需要拆出过多关键词,不用拆的过细
如”互联网校招“,可以拆出:互联网、联网、网校、校招等关键词,但实际上我们没有这些意思
此时要使用拆分出尽可能少但满足用户需求的词语——ik_smart
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String content;
// 将数据库中帖子存到es服务器里,就可以去es服务器中搜索这些帖子了
@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3)
public class DiscussPost {
@Id // 与索引中id字段对应
private int id;
// userId为普通字段
@Field(type = FieldType.Integer)
private int userId;
// 搜帖子主要在title和content中查找
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String title;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String content;
// 不用在这些字段进行搜索,就不用analyzer和searchAnalyzer属性
@Field(type = FieldType.Integer)
private int type;