导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
</dependencies>
application.yml文件配置
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.0.155:9300
创建启动类
@SpringBootApplication
public class ESApplication {
public static void main(String[] args) {
SpringApplication.run(ESApplication.class,args);
}
}
模型类
@AllArgsConstructor
@NoArgsConstructor
@Data
@Document(indexName = "item", type = "docs", shards = 1, replicas = 1)
public class Item implements Serializable {
@Id
private Long id;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title; //标题
@Field(type = FieldType.Keyword)
private String category;// 分类
@Field(type = FieldType.Keyword)
private String brand; // 品牌
@Field(type = FieldType.Double)
private Double price; // 价格
@Field(type = FieldType.Keyword,index = false)
private String images; // 图片地址
}
创建索引和映射
@RunWith(SpringRunner.class)
@SpringBootTest
public class EsTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 测试创建索引和映射
*/
@Test
public void addIndexTest(){
elasticsearchTemplate.createIndex(Item.class);
elasticsearchTemplate.putMapping(Item.class);
}
}
删除索引
@Test
public void delIndexTest(){
elasticsearchTemplate.deleteIndex(Item.class);
}
更简单的文档操作
定义接口继承
public interface ItemMapper extends ElasticsearchRepository<Item,Long> {
}
新增文档
@Test
public void addDocTest(){
Item item = new Item(1L, "小米手机9", " 手机","小米", 3499.00, "http://image.es.com/13123.jpg");
itemRepository.save(item);
}
批量新增
@Test
public void addDocsTest(){
List<Item> list = new ArrayList<>();
list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3689.00, "http://image.es.com/123123.jpg"));
list.add(new Item(3L, "华为META20", " 手机", "华为", 4499.00, "http://image.es.com/333.jpg"));
list.add(new Item(4L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.es.com/131223.jpg"));
list.add(new Item(5L, "荣耀V10", "手机", "华为", 2799.00, "http://image.es.com/131123.jpg"));
list.add(new Item(6L, "Nova", "手机", "华为", 2999.00, "http://image.es.com/131123.jpg"));
// 接收对象集合,实现批量新增
itemRepository.saveAll(list);
}
修改文档(和新增一样的接口,请求方式改为PUT)
基本查询
查询全部并根据价格升序
@Test
public void queryTest(){
Iterable<Item> items = itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
for (Item item : items) {
System.out.println(item);
}
}
/* output
Item(id=3, title=华为META20, category= 手机, brand=华为, price=4499.0, images=http://image.es.com/333.jpg)
Item(id=4, title=小米Mix2S, category=手机, brand=小米, price=4299.0, images=http://image.es.com/131223.jpg)
Item(id=2, title=坚果手机R1, category= 手机, brand=锤子, price=3689.0, images=http://image.es.com/123123.jpg)
Item(id=1, title=小米手机8, category= 手机, brand=小米, price=3499.0, images=http://image.es.com/13123.jpg)
Item(id=6, title=Nova, category=手机, brand=华为, price=2999.0, images=http://image.es.com/131123.jpg)
*/
简单原生方式查询
@Test
public void queryTest2(){
// 词条查询
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");
// 执行查询
Iterable<Item> items = itemRepository.search(queryBuilder);
items.forEach(System.out::println);
}
/* output
Item(id=1, title=小米手机8, category= 手机, brand=小米, price=3499.0, images=http://image.es.com/13123.jpg)
Item(id=4, title=小米Mix2S, category=手机, brand=小米, price=4299.0, images=http://image.es.com/131223.jpg)
*/
复杂原生方式查询
@Test
public void queryTest3(){
//创建查询构建器
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//结果过滤
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"id","title","price"},null));
//添加查询条件
queryBuilder.withQuery(QueryBuilders.matchQuery("title","小米手机"));
//排序
queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
//分页
queryBuilder.withPageable(PageRequest.of(0,2));
//查询
Page<Item> result = itemRepository.search(queryBuilder.build());
long totalElements = result.getTotalElements();
System.out.println("总记录个数: "+totalElements);
int totalPages = result.getTotalPages();
System.out.println("总页数个数: "+totalPages);
List<Item> itemList = result.getContent();
itemList.forEach(System.out::println);
}
/* output
总记录个数: 3
总页数个数: 2
Item(id=4, title=小米Mix2S, category=null, brand=null, price=4299.0, images=null)
Item(id=2, title=坚果手机R1, category=null, brand=null, price=3689.0, images=null)
*/
聚合为桶
@Test
public void queryTest4(){
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(
AggregationBuilders.terms("brands").field("brand"));
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Item> aggPage = (AggregatedPage<Item>) itemRepository.search(queryBuilder.build());
// 3、解析
// 3.1、从结果中取出名为brands的那个聚合,
// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍历
for (StringTerms.Bucket bucket : buckets) {
// 3.4、获取桶中的key,即品牌名称
System.out.println("Key: "+bucket.getKeyAsString());
// 3.5、获取桶中的文档数量
System.out.println("Value: "+bucket.getDocCount());
}
}
/* output
Key: 华为
Value: 3
Key: 小米
Value: 2
Key: 锤子
Value: 1
*/