本文基于SpringBoot 2.1.1.RELEASE版本配置,搭建的elasticsearch 6.4.3版本(7.1版本和当前的springData版本不兼容),
依赖spring-data-elasticsearh 3.1.3.RELEASE版本
添加依赖
添加maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
添加配置参数
#配置es节点信息,逗号分隔,如果没有指定,则启动ClientNode(9200端口是http查询使用的。9300集群使用。这里使用9300.)
spring.data.elasticsearch.clusterNodes:192.168.1.41:9300
spring.data.elasticsearch.clusterName:spt
使用示例
基于spring-data-elasticsearh操作和使用数据库差不多
1、实体配置
每个实体必须添加@Document注解,必须指定@Id字段
如果属性配置@Field,必须指定type类型
@Document(indexName = "sample-entity", type = "sample", shards = 1, replicas = 0, refreshInterval = "-1")
public class SampleEntity implements Serializable {
private static final long serialVersionUID = -7400751968589582556L;
@Id
private String id;
@Field(fielddata = true, type = FieldType.Text)
private String message;
private String name;
private String remark;
private int age;
//geter seter
}
2、创建Repository接口
Repository接口不需要添加任何注解,只需继承接口(ElasticsearchRepository)即可,在其他地方可以直接@Autowired使用
public interface SampleEntityRepository extends ElasticsearchRepository<SampleEntity, String>{
}
3、操作代码示例
除了自己创建的Repository接口外,还有一个通用的模板类可以直接使用ElasticsearchTemplate
索引操作
@Autowired
private ElasticsearchTemplate template;
public void createIndex() {
// 创建索引
template.createIndex(SampleEntity.class);
// 更新mapping配置
template.putMapping(SampleEntity.class);
// 删除索引
template.deleteIndex(SampleEntity.class);
// 刷新索引
template.refresh(SampleEntity.class);
}
保存数据
@Autowired
private SampleEntityRepository repository;
public void addData() {
for (int i = 1; i <= 15; i++) {
String documentId = RandomUtils.generateInt(6) + i;
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
sampleEntity.setMessage(documentId + "上海");
sampleEntity.setAge((int) (i * (Math.random() * 100)));
sampleEntity = repository.save(sampleEntity);
}
}
查询数据
text类型的字段默认是不允许排序的,如果一定要排序,则需要在对应的实体属性上增加注解 @Field(fielddata = true, type = FieldType.Text)
然后,调用template.putMapping(SampleEntity.class)方法,更新mapping配置后就可以排序了
public void search() {
// 指定指定排序
Sort sort = Sort.by(Direction.ASC, "message");
// 查询所有数据
Iterable<SampleEntity> list = repository.findAll(sort);
System.out.println(JsonUtil.obj2Json(list));
// 条件查询
QueryBuilder query = QueryBuilders.matchQuery("message", "上海");
// 指定分页参数
Pageable page = PageRequest.of(0, 5, sort);
list = repository.search(query, page);
System.out.println(JsonUtil.obj2Json(list));
}
在repository上直接指定查询条件
/** between条件 */
List<SampleEntity> findByAgeBetween(int from, int to);
@Query("{\"bool\" : {\"must\" : {\"match\" :{\"message\": \"?0\"}}}}")
// @Query("{\"term\" : {\"age\" : \"317\"}}")
// @Query("{\"match\" : {\"message\" : \"?0\"}}")
// @Query("{\"range\" : {\"age\" : {\"gte\":100} }}")
List<SampleEntity> findList(String msg);
其他查询示例
/** 分词精确查询 */
@Test
public void search3() {
QueryBuilder query = QueryBuilders.termsQuery("age", new int[] { 91, 378 });
Iterable<SampleEntity> list = repository.search(query);
System.out.println(JsonUtil.obj2Json(list));
}
/** or 查询 */
@Test
public void search4() {
//
QueryBuilder query1 = QueryBuilders.termsQuery("age", new int[] { 91, 378 });
QueryBuilder query2 = QueryBuilders.matchQuery("message", "14149910");
BoolQueryBuilder builder = QueryBuilders.boolQuery().should(query1).should(query2);
Iterable<SampleEntity> list = repository.search(builder);
System.out.println(JsonUtil.obj2Json(list));
}
/** and 查询 */
@Test
public void search5() {
// and 查询
QueryBuilder query1 = QueryBuilders.termsQuery("age", new int[] { 91, 378 });
QueryBuilder query2 = QueryBuilders.matchQuery("message", "2958266");
BoolQueryBuilder builder = QueryBuilders.boolQuery().must(query1).must(query2);
Iterable<SampleEntity> list = repository.search(builder);
System.out.println(JsonUtil.obj2Json(list));
}
/** 关键字高亮查询 */
@Test
public void search7() {
QueryBuilder query2 = QueryBuilders.matchQuery("message", "14149910");
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(query2)
.withHighlightFields(new Field("message")).build();
Page<SampleEntity> list = template.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<SampleEntity> poems = new ArrayList<>();
SearchHits hits = response.getHits();
for (SearchHit searchHit : hits) {
if (hits.getHits().length <= 0) {
return null;
}
SampleEntity entity = new SampleEntity();
String highLightMessage = searchHit.getHighlightFields().get("message").fragments()[0].toString();
entity.setId(searchHit.getId());
Map<String, Object> map = searchHit.getSourceAsMap();
entity.setMessage(String.valueOf(map.get("message")));
entity.setAge(Integer.valueOf(map.get("age").toString()));
// 反射调用set方法将高亮内容设置进去
try {
PropertyUtils.setProperty(entity, "message", highLightMessage);
} catch (Exception e) {
e.printStackTrace();
}
poems.add(entity);
}
if (poems.size() > 0) {
return new AggregatedPageImpl<T>((List<T>) poems);
}
return null;
}
});
System.out.println(JsonUtil.obj2Json(list));
}
/** 范围 查询 */
@Test
public void search8() {
QueryBuilder query1 = QueryBuilders.rangeQuery("age").gt(20).lt(50);
Iterable<SampleEntity> list = repository.search(query1);
System.out.println(JsonUtil.obj2Json(list));
list = repository.findByAgeBetween(10, 20);
System.out.println(JsonUtil.obj2Json(list));
}
参考