Spring Boot (4) 整合 Elasticsearch

一、前言

本文将基于springboot 2.1.8.RELEASE 来整合 Elasticsearch

环境:elasticsearch-5.6.16

温馨小提示: ES服务端Kibana客户端官网下载地址: https://www.elastic.co/downloads/past-releases

二、Spring Boot 整合 Elasticsearch

1、pom.xml中引入es依赖

<!-- spring data es -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2、application.yml中配置es

spring:
  # es相关配置
  data:
    elasticsearch:
      # 配置集群名
      cluster-name: elasticsearch   # 访问 es服务端 `http://127.0.0.1:9200/` 填写 `cluster_name` 对应的值
      # 配置节点信息,逗号分隔,如果没有指定,则启动ClientNode 【 注:9200->图形界面端、9300->程序端 】
      cluster-nodes: 127.0.0.1:9300
      # 开启 Elasticsearch 仓库(默认值:true)
      repositories:
        enabled: true

3、redis和es冲突问题

如上配置后,可以先启动一下项目,可能运行后会出现如下问题:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.IllegalStateException: availableProcessors is already set to [8], rejecting [8]

错误原因:程序的其他地方使用了Netty,这里指redis。这影响在实例化传输客户端之前初始化处理器的数量。 实例化传输客户端时,我们尝试初始化处理器的数量。 由于在其他地方使用Netty,因此已经初始化并且Netty会对此进行防范,因此首次实例化会因看到的非法状态异常而失败。

解决:在启动类中加上如下配置

System.setProperty("es.set.netty.runtime.available.processors","false");
在这里插入图片描述

注:虽然上面的方式能解决错误,服务可以正常启动,但是启动测试类时还是会报错哦!!!

因此es配置文件中需配置在RedisConfig之前装配,并且指定初始化时再一次添加忽略es中netty的一些配置!!!

ElasticsearchConfig 配置文件如下:

@Configuration
@AutoConfigureBefore(RedisConfig.class) // `RedisConfig.class`为redis配置文件
public class ElasticsearchConfig {

    @PostConstruct
    void init() {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }

    @Bean(name = "elasticsearchTemplate")
    public ElasticsearchTemplate elasticsearchTemplate(Client client, ElasticsearchConverter converter) {
        try {
            return new ElasticsearchTemplate(client, converter);
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    @Bean
    public ElasticsearchConverter elasticsearchConverter(
            SimpleElasticsearchMappingContext mappingContext) {
        return new MappingElasticsearchConverter(mappingContext);
    }

    @Bean
    public SimpleElasticsearchMappingContext mappingContext() {
        return new SimpleElasticsearchMappingContext();
    }

}

4、问题:failed to load elasticsearch nodes

如果出现如下问题:

failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{6VrRZl9ISEy3MT0rx2Vd2w}{127.0.0.1}{127.0.0.1:9300}]

① 尝试修改es服务端配置文件 network.host: 127.0.0.1

在这里插入图片描述

cluster-name集群名是否一致

③ 如果检查完以上2种情况后,还是报同样的错误,就要考虑是否为版本问题哦,小编刚开始处于新鲜感使用的是目前最新版elasticsearch-7.5.1,而spring-boot-starter-data-elasticsearch中的spring-data-elasticsearch3.1.10.RELEASE版本不支持高版本的es,因此版本选择要注意哦!!!

三、Elasticsearch增删改查API

1、创建索引并建立类型映射

温馨小提示:注意包名不要导错哦!!!

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * <p> 测试 </p>
 *
 * @author : zhengqing
 * @description : indexName:索引库     type:类型(可理解为mysql数据库中的表名)
 * @date : 2019/12/27 14:47
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "zq_test", type = "user")
public class User {
    @Id
    private Long id;

    @Field(type = FieldType.Keyword)
    private String name;

//    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String intro;

    @Field(type = FieldType.Integer)
    private Integer age;
}
@Component
public interface UserRepository extends ElasticsearchRepository<User, Long> { }
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class ESTest {

    @Autowired
    private ElasticsearchTemplate template;

    /**
     * 创建索引,并且建立类型映射
     */
    @Test
    public void test() throws Exception {
        // 创建索引
        template.createIndex(User.class);
        // 类型映射 - 自定义映射
        template.putMapping(User.class);
    }

}

运行后,在 http://127.0.0.1:5601/app/kibana#/dev_tools 中执行命令 GET zq_test/_mapping/user 查看类型映射

在这里插入图片描述

2、简单的增删改查

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class ESTest {

    @Autowired
    private UserRepository repository;

    @Test // 新增1个
    public void testAdd() throws Exception {
        User user = new User(1L, "zheng qing", "zheng qing is a programmer!", 18);
        repository.save(user);
    }

    @Test // 批量添加
    public void testBatchAdd() throws Exception {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            User user = new User(i + 2L, "zheng qing" + i + 1, "zheng qing is a programmer!", 18 + i );
            list.add(user);
        }
        repository.saveAll(list);
    }

    @Test // 获取1个
    public void testGetOne() throws Exception {
        System.out.println(repository.findById(1L));
    }

    @Test // 获取全部
    public void testGetAll() throws Exception {
        Iterable<User> all = repository.findAll();
        for (User user : all) {
            System.out.println(user);
        }
    }

    @Test // 新增、修改 (判断是否有id即可~)
    public void testUpdate() throws Exception {
        Optional<User> byId = repository.findById(1L);
        User user = byId.get();
        System.out.println(user);
        user.setName("zq");
        repository.save(user);
        System.out.println(repository.findById(1L));
    }

    @Test  // 删除
    public void testDel() throws Exception {
        repository.deleteById(1L);
        //repository.deleteAll();;
    }
    
}

3、高级查询(过滤)+分页+排序

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class ESTest {

    @Autowired
    private UserRepository repository;

    @Test // DSL查询与过滤+分页+排序
    public void testNativeSearchQueryBuilder() throws Exception {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        //模糊查询
        bool.must(QueryBuilders.matchQuery("intro", "zheng"));
        //精确过滤
        List<QueryBuilder> filters = bool.filter();
        filters.add(QueryBuilders.rangeQuery("age").gte(0).lte(200));
        builder.withQuery(bool); //query bool must(filter)
        //排序
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC));
        //分页   注:当前页从0开始
        builder.withPageable(PageRequest.of(0, 10));
        //截取字段
        builder.withSourceFilter(new FetchSourceFilter(new String[]{"name", "age"}, null));
        //构造查询条件
        NativeSearchQuery query = builder.build();
        //查询
        Page<User> page = repository.search(query);
        System.out.println("总数:" + page.getTotalElements());
        System.out.println("总页数:" + page.getTotalPages());
        for (User user : page.getContent()) {
            System.out.println(user);
        }
    }

}

本文案例demo源码

https://gitee.com/zhengqingya/java-workspace

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容