赞
踩
目录
(1)是什么:
Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。
Lucene 可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。但Lucene 只是一个基于java下的库,需要使用 Java 并要将其集成到你的应用中才可进行使用。而Elasticsearch 则是基于Lucene 下实现的开源搜索引擎。
Elasticsearch 基于分布式进行实时文件存储,每个字段都被索引并可被搜索,并可进行实时分析。同事由于基于分布式,可以扩展到上百台服务器,处理PB级结构化或非结构化数据。
(2)核心概念:
elasticsearch可归类于NoSQL的一种,其主要包含index(索引)、type(类型,elasticsearch 7.x后已被舍弃)、Document(文档)、Fields(字段)。
类比于MySQL如下:
其实现的核心在于倒排索引: 指的是将文档内容中的单词作为索引,将包含该词的文档 ID 作为记录。
一般的sql中都是正排索引,即以表中的唯一标识id作为索引,通过主键索引找到文档其他内容(具体请参考mysql存储结构)。
而elasticsearch通过关键字作为索引反向找到文档ID,可以高效的实现全文检索。
如我们有以下两条记录:
id | content | writer |
1 | 这是一条测试数据,测试elasticsearch | seven |
2 | 这是第二条、测试数据,试一下elasticsearch搜索 | seven |
以上两条数据,在mysql中id为主键,当我们以elasticsearch以关键词搜索去搜查所有和elasticsearch有关的content时,在没有为content建索引的情况下,无法走主键索引,mysql会进行全表检索,效率一般。
而elasticsearch中会为content建立倒排索引,根据content找到对应的id,返回搜索结果,效率快鱼mysql。并且,整个搜索过程中我们不需要做任何文本的模糊匹配。
(3)应用场景:
ElasticSearch作为一个便于使用的分布式全文搜索引擎,常被用于各种搜索场景中:
总之言之, ElasticSearch是一个优秀的检索工具,可以对各类内容进行快速检索,并返回结果:
(检索关键词并进行高亮)
一般情况我们会在数据存入数据库前,把需要检索的字段作为ElasticSearch的索引和需要返回的数据存入ElasticSearch(比如电商平台达到商品标题),然后在搜索时使用ElasticSearch进行全文检索,快速返回相关结果。
下面对springboot集成elasticsearch进行演示:
pom依赖文件:
- <properties>
- <java.version>1.8</java.version>
- <elasticsearch.version>7.6.1</elasticsearch.version>
- </properties>
-
- <dependencies>
- <!-- fastjson -->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.70</version>
- </dependency>
- <!-- ElasticSearch -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- <!-- web -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!-- lombok 需要安装插件 -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- <!-- test -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
此处需要注意的是springboot自带的ElasticSearch版本为6.8.5 ,如果你使用的是其他版本的ElasticSearch请注意指定版本号。
config配置文件,对ElasticSearch进行连接:
- @Configuration
- public class ElasticSearchConfig {
- @Bean
- public RestHighLevelClient restHighLevelClient(){
- RestHighLevelClient client = new RestHighLevelClient(
- RestClient.builder(
- new HttpHost("127.0.0.1",9200,"http")
- )
- );
- return client;
- }
- }
至此,我们皆可以通过 RestHighLevelClient 对ElasticSearch进行使用。
下面对 ElasticSearch进行使用,进行查询并高亮关键词。
首先我们建立索引:user,并存入以下数据:
然后,我们在业务类编写查询方法:
- //查询
- public List<User> searchUserByKeyword(String keyword,int pageNo,int pageSize) throws IOException {
- if (pageNo<=1){
- pageNo=1;
- }
- //条件查询
- SearchRequest searchRequest = new SearchRequest("user");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
-
- //分页
- searchSourceBuilder.from(pageNo);
- searchSourceBuilder.size(pageSize);
-
- //匹配关键词(类似于模糊查询)
- //MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("sign",keyword);
- //组合查询
- BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
- //and查询,所有条件都要符合; or查询可以使用queryBuilder.should
- queryBuilder.must(QueryBuilders.matchQuery("sign",keyword));
- queryBuilder.must(QueryBuilders.matchQuery("statue","use"));
- //精确匹配
- //TermQueryBuilder queryBuilder = QueryBuilders.termQuery("sign",keyword);
- searchSourceBuilder.query(queryBuilder);
-
- //设置高亮
- //highlightBuilder.requireFieldMatch(false); //只需要高亮第一个
- searchSourceBuilder.highlighter(new HighlightBuilder().field("sign"));
-
- //执行
- searchRequest.source(searchSourceBuilder);
- SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
-
- //解析结果
- List<User> list = new ArrayList<>();
- for (SearchHit hit: response.getHits().getHits()){
- //解析高亮字段
- Map<String, HighlightField> highlightFields = hit.getHighlightFields();
- HighlightField sign = highlightFields.get("sign");
- //获取原字段
- Map<String, Object> oldUser = hit.getSourceAsMap();
- //将高亮替换原字段内容
- StringBuilder stringBuilder = new StringBuilder();
- if (sign!=null){
- Text[] texts = sign.fragments();
- for (Text t:texts){
- stringBuilder.append(t);
- }
- log.info("替换:"+stringBuilder);
- oldUser.put("sign",stringBuilder.toString());
- }
-
- User user = JSONObject.parseObject(hit.getSourceAsString(),User.class);
- user.setSign(oldUser.get("sign").toString());
- list.add(user);
- }
- return list;
- }
ElasticSearch的match配置是拆字匹配,即关键词为“测试”,那么会查询出所有目标字段中包含“测”和“试”任一字符的结果;若为“java”则不会对字母进行拆分,会保持整个单词完整。
上述代码需要注意的是,高亮的字段必须是查询的字段,才可以对查询的关键词进行高亮处理,否则高亮字段会为空。
编写controller进行测试:
- @RestController
- public class SearchController {
-
- @Resource
- private SearchService searchService;
-
- @GetMapping("/test")
- public List<User> test(@RequestParam("keyword")String keyword) throws IOException {
- return searchService.searchUserByKeyword(keyword,0,5);
- }
- }
结果:
成功查询所有sign包含java关键词且statue为use的用户,并对java关键词进行高亮(em标签,需要使用html进行解析)。
拓展:
(1)ElasticSearch还可以对搜索结果进行排序:
searchSourceBuilder.sort("age");
上述代码即根据age字段对搜索结果进行排序。
(2)过滤查询条件:
- BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
- //过滤statue!=use的数据
- queryBuilder.filter(QueryBuilders.matchPhraseQuery("statue","use"));
- //过滤age不大于20的数据
- queryBuilder.filter(QueryBuilders.rangeQuery("age").gt(20));
具体还有很多查询条件,具体可参考ElasticSearch官网文档。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。