Spring Boot集成ElasticSearch实现搜索引擎的示例

时间:2021-05-20

Elastic Search是一个开源的,分布式,实时搜索和分析引擎。Spring Boot为Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置。Spring Boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'StarterPOM'。

ElasticSearch作为搜索引擎,我们需要解决2大问题:

1, 如何将被搜索的数据在ES上创建反向索引
2, Java代码如何与ES交互

其中第一个大问题又分为两个小问题

1.1,如何初始化已有的数据
1.2,如何同步增量数据

第二个大问题也有两种集成方式

2.1 Spring Data 9300端口集成
2.2 Restful API 9200端口集成

本篇先解决第二大问题。

第一种方式,利用RestAPI方式,也叫Jest方式:

示例代码:https://github.com/yejingtao/forblog/tree/master/demo-jest-elasticsearch

Pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:///yejingtao/forblog/tree/master/demo-data-elasticsearch

pom.xml依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>yejingtao.demo.springcloud</groupId> <artifactId>demo-data-elasticsearch</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-data-elasticsearch</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> </dependencies> </project>

不再引用Jest。

application.yml:

server: port: 7081 spring: data: elasticsearch: cluster-nodes: 192.168.226.133:9300 cluster-name: my-es repositories: enabled: true

注意这里是9300端口

Controller、主程序、Service接口同Jest项目不变,不再罗列

实体类稍作变化,指定ES中的index和type:

@Document(indexName="index_entity", type="tstype")

多一个Repository接口,无需实现类,spring data标准用法:

/** * Entity ES操作类 * @author yejingtao * */ public interface EntityRepository extends ElasticsearchRepository<Entity,Long>{ }

Service实现类与Jest的天壤之别了,从语法上可以看出更像是对数据库层的操作:

@Service public class CityESServiceImpl implements CityESService{ private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class); int PAGE_SIZE = 15; //默认分页大小 int PAGE_NUMBER = 0; //默认当前分页 String SCORE_MODE_SUM = "sum"; //权重分求和模式 Float MIN_SCORE = 10.0F; //由于无相关性的分值默认为1, 设置权重分最小值为10 @Autowired EntityRepository entityRepository; /** * 保存内容到ES */ @Override public Long saveEntity(Entity entity) { Entity entityResult = entityRepository.save(entity); return entityResult.getId(); } /** * 在ES中搜索内容 */ @Override public List<Entity> searchEntity(int pageNumber, int pageSize, String searchContent){ if(pageSize==0) { pageSize = PAGE_SIZE; } if(pageNumber<0) { pageNumber = PAGE_NUMBER; } SearchQuery searchQuery = getEntitySearchQuery(pageNumber,pageSize,searchContent); LOGGER.info("\n searchCity: searchContent [" + searchContent + "] \n DSL = \n " + searchQuery.getQuery().toString()); Page<Entity> cityPage = entityRepository.search(searchQuery); return cityPage.getContent(); } /** * 组装搜索Query对象 * @param pageNumber * @param pageSize * @param searchContent * @return */ private SearchQuery getEntitySearchQuery(int pageNumber, int pageSize, String searchContent) { FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() .add(QueryBuilders.matchPhraseQuery("name", searchContent), ScoreFunctionBuilders.weightFactorFunction(1000)) //.add(QueryBuilders.matchPhraseQuery("other", searchContent), //ScoreFunctionBuilders.weightFactorFunction(1000)) .scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE); //设置分页,否则只能按照ES默认的分页给 Pageable pageable = new PageRequest(pageNumber, pageSize); return new NativeSearchQueryBuilder().withPageable(pageable).withQuery(functionScoreQueryBuilder).build(); } }

测试方式同Jest。

这两种方式,从设计上来讲属于两种思路,Spring Data的思路就是将ElasticSearch当自家的数据仓库来管理,直接通过Java客户端代码操作ES;Jest的思路是将ElasticSearch当为独立的服务端,自己作为客户端用兼容性最强的RestFul格式来与之交互。
个人比较倾向于Jest方式,第一兼容性好,不需要考虑版本的问题。第二,从ElasticSearch本身的设计上来分析,9200是对外服务端口,9300是内部管理和集群通信端口,请求9200获取搜索服务更符合ES的设计初衷,不会影响集群内部的通信。
以上比较分析仅代表个人观点,欢迎大神么交流批评。希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章