以POJO为中心模型用于与Elastichsearch文档交互,并轻松编写存储库样式的数据访问层框架
我们学习的是底层封装了Rest High Level的ElasticsearchRestTemplate模板类型。需要使用Java API Client(Transport),则应用ElasticsearchTemplate模板类型即可。两种类型中的方法API几乎完全一样,学会了一个,另外一个主要就是配置和类型的区别。当然了,每个不同版本的框架,在方法API上还是有些差异的。
1.导入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
2.yml配置
# ElasticsearchRestTemplate客户端的配置
spring:
elasticsearch:
rest:
uris: http://127.0.0.1:9200 # ES服务器所在位置。集群多节点地址用逗号分隔。默认http://localhost:9200
3.创建实体类
* Document - 描述类型和索引的映射。
* indexName - 索引名称
* shards - 主分片数量。默认值 1。
* replicas - 副本分片数量。默认值 1。
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "xy_student",shards = 1,replicas = 0)
public class Student {
* Id - 当前注解所在字段和主键值一致,没有次注解,则自动生成主键
* Field - 当前属性和索引中的字段映射规则。
* name - 字段名称。默认和当前类型属性名一致。
* type - 字段类型。默认使用FieldType.AUTO。自动识别。
* analyzer - 分词器。所有的Text类型字段默认使用standard分词器。
* index - 是否创建索引。默认值 true。
* format - 如果字段类型是date日期类型。此属性必须配置,用于设置日期格式化规则,使用DateFormat类型中的常量定义。
@Id
@Field(name="sid",type = FieldType.Integer)
private Integer sid;
@Field(name="sname",type = FieldType.Text,analyzer = "ik_max_word")
private String sname;
@Field(name="score",type = FieldType.Double)
private Double score;
@Field(name="birth",type = FieldType.Date,format = DateFormat.year_month_day)
private Date birth;
}
@Autowired
private ElasticsearchRestTemplate restTemplate;
IndexOperations indexOps = restTemplate.indexOps(Student.class);
1.创建索引
indexOps.create();
2.设置映射: 在商业开发中,几乎不会使用框架创建索引或设置映射。因为这是架构或者管理员的工作。且不适合使用代码实现
indexOps.putMapping(indexOps.createMapping());
3.删除索引
restTemplate.indexOps(Student.class).delete();
简单CURD
1.新增文档
如果索引不存在,新增文档时自动创建索引。但是不使用类上的映射配置,使用默认映射.所以一定要先通过代码进行mapping设置,或直接在elasticsearch中通过命令创建所有field的mapping(推荐)
Student zs = elasticsearchRestTemplate.save(new Student(1, "zs", 0.55, new Date()));
System.out.println(zs);
2.批量新增文档
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(1, "zs", 0.55, new Date()));
students.add(new Student(2, "sdf", 0.22, new Date()));
students.add(new Student(3, "df", 0.33, new Date()));
Iterable<Student> save = elasticsearchRestTemplate.save(students);
System.out.println(save.toString());
3.主键查询文档
Student student = restTemplate.get("3", Student.class);
4.删除文档
// 删除类型对应的索引中的指定主键数据,返回删除数据的主键。注意:Elasticsearch中的文档主键都是字符串类型的。
String response = restTemplate.delete("1", Student.class);
5.更新文档
* save方法,可以覆盖同主键数据。全量替换
* update更新,部分更新
@Test
public void testUpdate(){
UpdateQuery query =UpdateQuery.builder("2")
.withDocument(Document.parse("{\"hobbies\":[\"郭麒麟\", \"郭汾阳\"]}"))
.build();
UpdateResponse response = restTemplate.update(query, IndexCoordinates.of("stu_index"));
System.out.println(response.getResult());
}
query string 查询
@Test
void contextsxLsoads() {
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("sname:zs");
Query query = new NativeSearchQueryBuilder()
.withQuery(queryBuilder) // 提供具体的条件。
.build();
SearchHits<Student> hits = elasticsearchRestTemplate.search(query, Student.class);
System.out.println("搜索结果数据个数是: " + hits.getTotalHits());
for (SearchHit<Student> hit : hits) {
// 源数据,就是保存在Elasticsearch中的数据
Student content = hit.getContent();
System.out.println("源数据:" + content);
}
}
DSL 查询
1.搜索全部
@Test
public void testMatchAll(){
SearchHits<Student> hits = restTemplate.search(
new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.build(), Student.class);
for(SearchHit<Student> hit : hits){
System.out.println(hit.getContent());
}
}
2.match搜索
SearchHits<Student> hits = restTemplate.search(
new NativeSearchQueryBuilder()
.withQuery(
QueryBuilders.matchQuery(
"name",
"于谦")
).build(),Student.clas);
3.短语搜索,完全匹配Match Phrase
SearchHits<Student> hits = restTemplate.search(
new NativeSearchQueryBuilder()
.withQuery(
QueryBuilders.matchPhraseQuery(
"hobbies",
"烫头"
)
)
.build(),
Student.class
);
4.范围搜索Range 搜索
SearchHits<Student> hits =
restTemplate.search(
new NativeSearchQueryBuilder()
.withQuery(
QueryBuilders.rangeQuery("age")
.lte(35).gte(30)
)
.build(),
Student.class
);
5.Bool 搜索,多条件同时满足
@Test
void contextswLsoads() {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
List<QueryBuilder> must = boolQueryBuilder.must();
must.add(QueryBuilders.matchQuery("sname","zs"));
must.add(QueryBuilders.rangeQuery("score").gt(0).lt(0.5));
Query queryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).build();
SearchHits<Student> search = elasticsearchRestTemplate.search(queryBuilder, Student.class);
}
6.分页和排序
* PageRequest类型中,提供静态方法of(int page, int size[, Sort sort]);
* page - 查询第几页,页码数字从0开始计数。
* size - 查询多少行。
* Sort - 具体的排序规则。可选参数。
SearchHits<Student> hits =
restTemplate.search(
new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.withPageable(
PageRequest.of(0, 2,
Sort.by(
Sort.Order.desc("age"),
Sort.Order.asc("id")
)
)
)
.build(),
Student.class
);
7.高亮处理
@Test
public void testQueryHighLight(){
// 创建高亮字段,必须和具体的字段名绑定。
HighlightBuilder.Field field1 = new HighlightBuilder.Field("name");
// 高亮前缀
field1.preTags("");
// 高亮后缀
field1.postTags("");
// 分段的每段字符数
field1.fragmentSize(Integer.MAX_VALUE);
// 分段后,返回几段
field1.numOfFragments(1);
Query query =
new NativeSearchQueryBuilder()
.withQuery(
QueryBuilders.matchQuery(
"name",
"于谦")
)
.withHighlightFields(field1)
.build();
SearchHits<Student> hits =
restTemplate.search(query, Student.class);
for (SearchHit<Student> hit : hits){
// 获取源数据
Student content = hit.getContent();
// 找高亮数据
List<String> hl = hit.getHighlightField("name");
// 判断是否有高亮数据
if(hl != null && hl.size() > 0){
// 有高亮数据
content.setName(hl.get(0));
}
System.out.println(content);
}
}