1、引入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
2、配置yml
spring:
data:
elasticsearch:
cluster-name: elasticsearch # 集群名字
cluster-nodes: localhost:9300 # 集群结点,多个节点用逗号隔开
Repository
就是ES的Dao
,和JPA的里的用法大致一样。
这里以Article
类为例,介绍了注解
常用的用法,更多用法可以百度~
@Data // lombok生成get/set
// indexName:ElasticSearch里的索引名 type:类型名
@Document(indexName = "lcy_article",type = "article")
public class Article {
@Id // Id标识主键
// Field标识属性,type:属性类型,store:是否存储,默认否,index:是否索引,默认是,analyzer:分词的方式
@Field(type = FieldType.Long,store = true)
private Long id;
@Field(type = FieldType.Keyword,store = true)
private String author;
@Field(type = FieldType.Text,store = true,analyzer = "ik_smart")
private String title;
@Field(type = FieldType.Text,store = true,analyzer = "ik_smart")
private String content;
@Field(type = FieldType.Integer,store = true)
private Integer price;
public Article() {
}
public Article(Long id, String author, String title, String content,Integer price) {
this.id = id;
this.author = author;
this.title = title;
this.content = content;
this.price = price;
}
@Override
public String toString() {
return "ID:" + id + "\t\t标题:" + title + "\t\t作者:" + author + "\t\t内容:" + content;
}
}
ElasticSearchRepository
接口// ElasticsearchRepository<文档类型,主键类型>
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
// 自定义查询 - 符合方法命名规范即可
List<Article> findByTitle(String title);
List<Article> findByIdBetween(Long start,Long end);
}
启动类上需要添加EnableElasticsearchRepositories
注解扫描Repository
接口。
@SpringBootApplication
@EnableElasticsearchRepositories(basePackages = "pers.liuchengyin.es.repository") // 配置ES扫描repository的包
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class ArticleTest {
@Autowired
private ElasticsearchTemplate template;
@Autowired
private ArticleRepository articleRepository;
/******************************************* 索引操作start *****************************************/
/**
* 创建索引并配置映射关系
*/
@Test
public void createIndex(){
template.createIndex(Article.class);
}
/**
* 配置映射关系 - 把类中的属性与es内部的对应
*/
@Test
public void createMapping(){
template.putMapping(Article.class);
}
/**
* 删除索引
*/
@Test
public void deleteIndex(){
template.deleteIndex(Article.class);
}
/******************************************* 索引操作end *****************************************/
/******************************************* 文档基本操作Repository start *****************************************/
/**
* 新增/修改文档
* ES没有提供修改的方法,只能通过新增的方式去完成修改
* 也就是说实际上是先删除,后新增的方式,需要保证主键Id一致
*/
@Test
public void addOrUpdateDocument(){
Article article = new Article(7L, "柳成荫", "Java高并发", "高并发很难啊",100);
articleRepository.save(article);
Article article6 = new Article(1L, "柳成荫", "Java基础", "Java基础要学扎实",90);
Article article1 = new Article(2L, "九月清晨", "Java高级", "一、集合框架及泛型1、集合框架是一套性能优良、使用方便的接口和类",100);
Article article2 = new Article(3L, "寻宝游戏", "SSM框架", "SSM框架提高了人们写代码的效率",100);
Article article3 = new Article(4L, "寻梦港", "SpringBoot框架", "SpringBoot框架在SSM的基础之上更进一层,省略了很多配置",100);
Article article4 = new Article(5L, "祖龙城", "SOA架构", "SOA架构解决了服务相关的问题",100);
Article article5 = new Article(6L, "不如吃茶去", "微服务架构", "微服务在SOA之上,将服务更加细致化",100);
List<Article> articles = new ArrayList<>();
articles.add(article1);
articles.add(article2);
articles.add(article3);
articles.add(article4);
articles.add(article5);
articles.add(article6);
articleRepository.saveAll(articles);
}
/**
* 根据Id删除文档
* 还可以直接传入文档删除,批量删除,全部删除等
*/
@Test
public void deleteDocument(){
articleRepository.deleteById(1L);
}
/**
* 分页查询
* 如果不是查询所有,会自动分页,10条数据
*/
@Test
public void selectPage(){
Page<Article> all = articleRepository.findAll(PageRequest.of(0, 3));
all.forEach(System.out::println);
}
/**
* 按指定字段排序
*/
@Test
public void selectSort(){
Iterable<Article> articles = articleRepository.findAll(Sort.by("id").ascending());
articles.forEach(System.out::println);
}
/**
* 自定义查询 - 根据Title查询
* 先分词后查询
*/
@Test
public void selectByTerm(){
List<Article> articles = articleRepository.findByTitle("Java");
articles.forEach(System.out::println);
}
/**
* 自定义查询 - 根据Id范围查询
*/
@Test
public void selectByIdScope(){
List<Article> articles = articleRepository.findByIdBetween(3L,5L);
articles.forEach(System.out::println);
}
/******************************************* 文档基本操作Repository end *****************************************/
/******************************************* 文档基本操作NativeSearchQuery start *****************************************/
/**
* 词条查询 - 精准查询
*/
@Test
public void termSearch(){
// 创建查询条件构建器
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 词条查询 - 根据Id查询
nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("id",1L));
// 构建查询
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 匹配查询
*/
@Test
public void matchSearch(){
// 创建查询条件构建器
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("title","Java"));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 布尔查询
*/
@Test
public void boolSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder
.withQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("title", "Java"))
.must(QueryBuilders.termQuery("id", 1L)));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 模糊查询
* 需要注意的是 - 可能是因为中文分词器的原因,对于英文模糊搜索无结果
* ? 表示一个未知的占位符
* * 表示0到n个任意占位符
*/
@Test
public void vagueSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("title","*架*"));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 分页查询 - 在模糊查询的基础上进行
*/
@Test
public void pageSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("title","*架*"));
// 分页
nativeSearchQueryBuilder.withPageable(PageRequest.of(0,3));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 排序查询 - 在模糊查询的基础上进行
*/
@Test
public void sortSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("title","*架*"));
// 按Id倒序排序
nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 过滤查询 - 不会计算匹配分
*/
@Test
public void filterSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.boolQuery().filter(QueryBuilders.matchQuery("author","柳")));
Page<Article> articles = articleRepository.search(nativeSearchQueryBuilder.build());
articles.forEach(System.out::println);
}
/**
* 聚合(分组)查询
* 注意要分组的字段类型要为 keyword
*/
@Test
public void aggregationSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 添加聚合,聚合类型为terms,聚合名称为authors,聚合字段为author
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("authors").field("author"));
// 查询(结果改为聚合类分页结果)
AggregatedPage<Article> articles = (AggregatedPage<Article>) articleRepository.search(nativeSearchQueryBuilder.build());
// 在查询结果中找到聚合 - 根据聚合名称
StringTerms author = (StringTerms) articles.getAggregation("authors");
// 获取查询到的桶(分组)
List<StringTerms.Bucket> buckets = author.getBuckets();
// 遍历桶
for (StringTerms.Bucket bucket : buckets) {
// 获取桶的Key
String keyAsString = bucket.getKeyAsString();
// 获取桶的数量(文档的数量)
long docCount = bucket.getDocCount();
System.out.println(keyAsString + ":" + docCount);
}
}
@Test
public void sonAggregationSearch(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("authors").field("author")
// 创建子聚合工程 - 对父聚合工厂的结果进行取平均值 - price
.subAggregation(AggregationBuilders.avg("avg").field("price")));
// 查询(结果改为聚合类分页结果)
AggregatedPage<Article> articles = (AggregatedPage<Article>) articleRepository.search(nativeSearchQueryBuilder.build());
// 在查询结果中找到聚合 - 根据聚合名称
StringTerms authors = (StringTerms) articles.getAggregation("authors");
// 获取查询到的桶(分组)
List<StringTerms.Bucket> buckets = authors.getBuckets();
// 遍历
for (StringTerms.Bucket bucket : buckets) {
// 获取父聚合字段名及文档数
System.out.println(bucket.getKeyAsString() + ":" + bucket.getDocCount());
System.out.println();
// 获取桶对应的avg
InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("avg");
System.out.println("平均price是:" + avg.getValue());
}
}
/******************************************* 文档基本操作NativeSearchQuery end *****************************************/
}
本文主要是Repository
的使用,实际上ElasticsearchTemplate
基本也能完成Repository
提供的功能。更多关于ElasticsearchTemplate
的使用可以百度,我这里就不做演示了(主要是我也没怎么了解hhh)。