文章目录
- 一、导入依赖和配置
- 1. 导入依赖
- 2. 配置连接
- 3. 解决启动Netty冲突
- 二、SpringData集成ES测试
- 1. 配置实体类与ES索引字段相对应
- `@Document(indexName = "discusspost", type = "_doc", shards = 5, replicas = 2)`
- `@Id`
- `@Field(type = FieldType.Integer)`
- `analyzer = "ik_max_word", searchAnalyzer = "ik_smart"`
- 2. dao层接口定义
- 3. 测试对ES服务器的CRUD基本操作
- 3.1 向ES库中添加数据
- `save(discussPostMapper.selectPost(241))`
- `saveAll(discussPostMapper.getPosts(101, 0, 100))`
- 3.2 修改ES库中的数据
- 3.3 删除数据
- `delete(discussPostMapper.selectDiscussPostById(231))`
- `deleteAll()`
- 3.4 搜索数据-ElasticsearchRepository
- `SearchQuery`
- `QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")`
- `SortBuilders.fieldSort("type").order(SortOrder.DESC)`
- `PageRequest.of(0, 10)`
- `withHighlightFields()`
- `new HighlightBuilder.Field("title").preTags("").postTags("")`
- `search(searchQuery)`
- `page.getTotalElements()`
- `page.getTotalPages()`
- `page.getNumber()`
- `page.getSize()`
- 测试结果:
- 3.5 搜索数据-ElasticsearchTemplate
- `new SearchResultMapper()`
- `HighlightField`
- `getFragments()`
- 测试结果
参考牛客网高级项目教程
狂神说Elasticsearch教程笔记
尚硅谷Elasticsearch教程笔记
一、导入依赖和配置
1. 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2. 配置连接
# ElasticsearchProperties
spring.data.elasticsearch.cluster-name=community
#TCP访问端口
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
3. 解决启动Netty冲突
-
如果不解决Netty冲突,启动ES时,会报错误
-
原因是ES启动时,会在Netty4Utils类的setAvailableProcessors方法中进行检查netty是否启动了,
-
解决策略是:将方法中留的set布尔变量设置为false,这样,就会中断检查
-
因此,在整个项目启动函数CommunityApplication中,设置初始化函数,将set的布尔值设置为false
@PostConstruct
public void init() {
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
二、SpringData集成ES测试
1. 配置实体类与ES索引字段相对应
@Document(indexName = "discusspost", type = "_doc", shards = 5, replicas = 2)
- indexName 对应的索引名称-没有创建,就自动创建一个
- type 对应的类型,逐渐舍去
- shards,replicas ,设定的分片和副本
@Id
- 必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"/id"
@Field(type = FieldType.Integer)
analyzer = "ik_max_word", searchAnalyzer = "ik_smart"
@Document(indexName = "discusspost", type = "_doc", shards = 5, replicas = 2)
public class DiscussPost {
@Id
private int id;
@Field(type = FieldType.Integer)
private int userId;
@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;
@Field(type = FieldType.Integer)
private int type;
@Field(type = FieldType.Integer)
private int status;
@Field(type = FieldType.Date)
private Date createTime;
@Field(type = FieldType.Integer)
private int commentCount;
@Field(type = FieldType.Double)
private double score;
...
}
2. dao层接口定义
ElasticsearchRepository<DiscussPost, Integer>
- SpringData对ES封装的处理ES数据CRUD的接口,基本的操作都能完成
- 接口中指定要操作的实体类型,以及文档id即实体类型主键的数据类型
@Repository
public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost, Integer> {
}
3. 测试对ES服务器的CRUD基本操作
3.1 向ES库中添加数据
save(discussPostMapper.selectPost(241))
@Test
public void testPUT() {
discussRepository.save(discussPostMapper.selectPost(241));
discussRepository.save(discussPostMapper.selectPost(242));
discussRepository.save(discussPostMapper.selectPost(243));
}
-
测试结果:
{
"discusspost": {
"aliases": {},
"mappings": {
"_doc": {
"properties": {
"commentCount": {
"type": "integer"
},
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"createTime": {
"type": "date"
},
"id": {
"type": "long"
},
"score": {
"type": "double"
},
"status": {
"type": "integer"
},
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"type": {
"type": "integer"
},
"userId": {
"type": "integer"
}
}
}
},
"settings": {
"index": {
"refresh_interval": "1s",
"number_of_shards": "5",
"provided_name": "discusspost",
"creation_date": "1648823705739",
"store": {
"type": "fs"
},
"number_of_replicas": "2",
"uuid": "u0zDxIykSbWUehgQXP3Wow",
"version": {
"created": "6040399"
}
}
}
}
}
saveAll(discussPostMapper.getPosts(101, 0, 100))
- 一次性插入多条数据-从offset到limit的所有条数据
@Test
public void testPUTList() {
discussRepository.saveAll(discussPostMapper.getPosts(101, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(102, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(103, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(111, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(112, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(131, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(132, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(133, 0, 100));
discussRepository.saveAll(discussPostMapper.getPosts(134, 0, 100));
}
-
结果测试
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 141,
"max_score": 1,
...
}
3.2 修改ES库中的数据
- 为保证数据同步,先在mysql中修改数据,再将数据重新保存覆盖进ES库中
@Test
public void testUpdate() {
DiscussPost post = discussPostMapper.selectPost(231);
post.setContent("我其实不是新人,哈哈哈");
discussRepository.save(post);
}
3.3 删除数据
delete(discussPostMapper.selectDiscussPostById(231))
deleteAll()
@Test
public void testDelete() {
discussRepository.deleteAll();
}
-
测试结果:
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
3.4 搜索数据-ElasticsearchRepository
SearchQuery
NativeSearchQueryBuilder
withQuery()
QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")
SortBuilders.fieldSort("type").order(SortOrder.DESC)
PageRequest.of(0, 10)
withHighlightFields()
new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>")
- 对指定字段的前后添加标签,前端可以用css渲染高亮
search(searchQuery)
- 根据之前设定的查询规则,进行搜索
- 返回Page类型的文档集合
page.getTotalElements()
page.getTotalPages()
page.getNumber()
page.getSize()
@Test
public void testSearchByRepository() {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
.withPageable(PageRequest.of(0, 10))
.withHighlightFields(
new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
).build();
Page<DiscussPost> page = discussRepository.search(searchQuery);
System.out.println(page.getTotalElements());
System.out.println(page.getTotalPages());
System.out.println(page.getNumber());
System.out.println(page.getSize());
for (DiscussPost post : page) {
System.out.println(post);
}
}
}
测试结果:
3.5 搜索数据-ElasticsearchTemplate
- 使用ElasticsearchRepository,虽也查询到了高亮,但无法将高亮标签与原数据进行组合,因此,很难实现高亮效果
- 因此,使用ElasticsearchTemplate 原生的API进行组装处理
new SearchResultMapper()
HighlightField
getFragments()
- getFragments()返回的是一个数组,因为匹配的不止一个,只高亮第一个匹配的结果即可
@Test
public void testSearchByTemplate() {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
.withPageable(PageRequest.of(0, 10))
.withHighlightFields(
new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
).build();
Page<DiscussPost> page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
SearchHits hits = response.getHits();
if (hits.getTotalHits() <= 0) {
return null;
}
List<DiscussPost> list = new ArrayList<>();
for (SearchHit hit : hits) {
DiscussPost post = new DiscussPost();
String id = hit.getSourceAsMap().get("id").toString();
post.setId(Integer.valueOf(id));
String userId = hit.getSourceAsMap().get("userId").toString();
post.setUserId(Integer.valueOf(userId));
String title = hit.getSourceAsMap().get("title").toString();
post.setTitle(title);
String content = hit.getSourceAsMap().get("content").toString();
post.setContent(content);
String status = hit.getSourceAsMap().get("status").toString();
post.setStatus(Integer.valueOf(status));
String createTime = hit.getSourceAsMap().get("createTime").toString();
post.setCreateTime(new Date(Long.valueOf(createTime)));
String commentCount = hit.getSourceAsMap().get("commentCount").toString();
post.setCommentCount(Integer.valueOf(commentCount));
HighlightField titleField = hit.getHighlightFields().get("title");
if (titleField != null) {
post.setTitle(titleField.getFragments()[0].toString());
}
HighlightField contentField = hit.getHighlightFields().get("content");
if (contentField != null) {
post.setContent(contentField.getFragments()[0].toString());
}
list.add(post);
}
return new AggregatedPageImpl(list, pageable,
hits.getTotalHits(), response.getAggregations(), response.getScrollId(), hits.getMaxScore());
}
});
System.out.println(page.getTotalElements());
System.out.println(page.getTotalPages());
System.out.println(page.getNumber());
System.out.println(page.getSize());
for (DiscussPost post : page) {
System.out.println(post);
}
}
测试结果
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)