SLK的个人博客

  • 首页

  • 搜索
LRU Stack ThreadLocal Nacos RejectedExecutionHandler Executor RocketMQ ConcurrentHashMap CyclicBarrier Semaphore CountDownLatch canal Unsafe Atomic BlockingQueue AQS ReentrantLock Synchronized MESI Volatile JMM BufferPool Explain MySQL 常量池 Arthas JVM调优 三色标记 CMS ParNew 垃圾收集器 G1 Java Redis Android HTTPDNS DNS ioc 爬虫 seleniumhq 推荐引擎 Mahout IM Netty Vert.x HashMap 梯子 翻墙 V2ray Docker 搜索引擎 SpringBoot elasticsearch

SpringBoot 集成 elasticsearch 搜索引擎

发表于 2020-04-04 | 分类于 Java | 0 | 阅读次数 301

SpringBoot 集成 elasticsearch 搜索引擎

添加maven依赖

  <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-elasticsearch</artifactId>
      <version>3.2.6.RELEASE</version>
  </dependency>

在Yaml配置中添加节点

其实这里可以改用nginx做负载均衡 不用把所有节点添加到yaml配置文件里

project:
  esearchNode:
    - 10.211.55.6:9200

接收配置文件参数的实体类

@Data
@ConfigurationProperties("project")
@Configuration
public class ProjectConfig {
    private List<String> esearchNode;
}

注入es 的Client Bean对象

@Slf4j
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class EsearchConfiguration extends AbstractElasticsearchConfiguration {
    private final ProjectConfig projectConfig;


    private InetSocketAddress createInetSocketAddress(String hostAndPorts) {
        Assert.isTrue(!StringUtils.isEmpty(hostAndPorts), "host and ports can not be null");
        String[] split = hostAndPorts.split(":");
        Assert.isTrue(split.length == 2, "host and ports is Unknown");
        return InetSocketAddress.createUnresolved(split[0], Integer.parseInt(split[1]));
    }

    /**
     * 配置要使用的客户端
     *
     * @return
     */
    @Override
    public RestHighLevelClient elasticsearchClient() {
        InetSocketAddress[] inetSocketAddresses = projectConfig.getEsearchNode().stream().map(this::createInetSocketAddress).toArray(InetSocketAddress[]::new);
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(inetSocketAddresses)
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

    /**
     * 使用元模型对象映射弹性搜索映射器。
     *
     * @return
     */
    @Bean
    @Override
    public EntityMapper entityMapper() {
        ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(),
                new DefaultConversionService());
        entityMapper.setConversions(elasticsearchCustomConversions());
        return entityMapper;
    }
}

添加Controller

@Slf4j
@RestController
@RequestMapping("/api/esearch")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Validated
public class EsearchController {
    private final ElasticsearchOperations elasticsearchOperations;


    @RequestMapping("insert")
    public UserModel insert() {
        AlternativeJdkIdGenerator alternativeJdkIdGenerator = new AlternativeJdkIdGenerator();
        UserModel userModel = new UserModel()
                .setAge(new Random().nextInt(29) + 1)
                .setNikeName("张三")
                .setUserId(alternativeJdkIdGenerator.generateId().toString());
        IndexQuery indexQuery = new IndexQueryBuilder()
                .withId(userModel.getUserId())
                .withObject(userModel)
                .build();

        String indexId = elasticsearchOperations.index(indexQuery);
        return userModel;
    }


    @RequestMapping("query")
    public List<UserModel> query(@NotBlank String nikeName, @NotNull Integer age) {
        CriteriaQuery criteriaQuery = new CriteriaQuery(
                Criteria.where("nikeName").is(nikeName).and("age").is(age)
        );
        return elasticsearchOperations.queryForList(criteriaQuery, UserModel.class);
    }
}

测试api接口 插入

springboot_elasticsearch_2

查询名字为张三 并且年龄 13的

可以看到 刚刚插入的数据已经被搜索出来了

springboot_elasticsearch_1

使用 ElasticsearchRepository

public interface UserRepository extends ElasticsearchRepository<UserModel, String> {
    /**
     * 根据昵称 和 年龄查询
     *
     * @param nikeName 名称
     * @param age      年龄
     * @return
     */
    List<UserModel> findByNikeNameAndAge(String nikeName, Integer age);
}

加上Repository包路径

@EnableElasticsearchRepositories(basePackages = "cn.pencilso.esearch.repository")
@Slf4j
@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class EsearchConfiguration extends AbstractElasticsearchConfiguration {
  ...

再次改动Controller

@Slf4j
@RestController
@RequestMapping("/api/esearch")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Validated
public class EsearchController {
    private final UserRepository userRepository;


    @RequestMapping("insert")
    public UserModel insert() {
        AlternativeJdkIdGenerator alternativeJdkIdGenerator = new AlternativeJdkIdGenerator();
        UserModel userModel = new UserModel()
                .setAge(new Random().nextInt(29) + 1)
                .setNikeName("张三")
                .setUserId(alternativeJdkIdGenerator.generateId().toString());
        return userRepository.save(userModel);
    }


    @RequestMapping("query")
    public List<UserModel> query(@NotBlank String nikeName, @NotNull Integer age) {
        return userRepository.findByNikeNameAndAge(nikeName, age);
    }
}

遇到的问题

userRepository.findByNikeNameAndAge 这种写法会调用两次Rest接口
最后跟踪RestCient 代码 查到,调用两次Rest接口是因为,先查询了一次count,然后会再次查询数据。
从源码层次来看Repository是为了强制分页,但是,查询到了itemCount后,创建了一个Page分页参数,页码是第一页,并且分页数量是itemCount,等于还是查询了所有。

springboot_elasticesearch_3

关于解决方案,在查询的时候,定义分页参数即可。如下:

    /**
     * 根据昵称 和 年龄查询
     *
     * @param nikeName 名称
     * @param age      年龄
     * @return
     */
    List<UserModel> findByNikeNameAndAge(String nikeName, Integer age, PageRequest pageRequest);

调用的地方

userRepository.findByNikeNameAndAge(nikeName, age, PageRequest.of(0,20))
文章内容参考自官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.6.RELEASE/reference/html/
# LRU # Stack # ThreadLocal # Nacos # RejectedExecutionHandler # Executor # RocketMQ # ConcurrentHashMap # CyclicBarrier # Semaphore # CountDownLatch # canal # Unsafe # Atomic # BlockingQueue # AQS # ReentrantLock # Synchronized # MESI # Volatile # JMM # BufferPool # Explain # MySQL # 常量池 # Arthas # JVM调优 # 三色标记 # CMS # ParNew # 垃圾收集器 # G1 # Java # Redis # Android # HTTPDNS # DNS # ioc # 爬虫 # seleniumhq # 推荐引擎 # Mahout # IM # Netty # Vert.x # HashMap # 梯子 # 翻墙 # V2ray # Docker # 搜索引擎 # SpringBoot # elasticsearch
Docker 部署 V2ray 实现翻墙 Websocket TLS Nginx
SpringBoot IOC 容器使用
  • 文章目录
  • 站点概览
宋龙宽

宋龙宽

87 日志
13 分类
53 标签
RSS
Github E-mail
Creative Commons
Links
  • 黑客派
  • Relyn
  • 张小妞的博客
  • ElasticSearch教程
© 2021 宋龙宽
由 Halo 强力驱动
|
主题 - NexT.Gemini v5.1.4