抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

写在前面

Docker搭建elaseticsearch 先看这篇文章完成Docker搭建elaseticsearch

之前看过一篇大佬文章,但是文章现在需要vip才可以查看,所以我重新总结一下。windows的小伙伴也可以安装docker,或者直接安装elaseticsearch也是可以的,yml配置需要改一下。

springboot整合elasticsearch

pom引入

<!--elasticsearch--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.1.6.RELEASE</version> <scope>compile</scope> </dependency>

yml配置

spring: data: elasticsearch: cluster-name: docker-cluster #集群名称 cluster-nodes: ip:9300 #配置es节点信息,逗号分隔,如果没有指定,则启动ClientNode properties: path: logs: ./elasticsearch/log #elasticsearch日志存储目录 data: ./elasticsearch/data #elasticsearch数据存储目录

配置只需这么些,接下来就写一些demo来玩一下elaseticsearch

构建Item类

@Document(indexName = "item",type = "docs", shards = 1, replicas = 0) public class Item { @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; // 价格

}

创建ItemRepository并继承ElasticsearchRepository,有兴趣的可以看一下底层源码

public interface ItemRepository extends ElasticsearchRepository<Item,Long>{ /** * @Description:根据价格区间查询 自定义查询 * @Param price1 * @Param price2 */ List<Item> findByPriceBetween(double price1, double price2); List<Item> findByTitle(String title1); List<Item> findByTitleIn(Collection<String> ss); }

创建索引 删除索引

@RunWith(SpringRunner.class) @SpringBootTest(classes = BootApplication.class) public class EsDemoApplicationTest{
@Autowired private ElasticsearchTemplate elasticsearchTemplate;
/** * @Description:创建索引,会根据Item类的@Document注解信息来创建 */ @Test public void testCreateIndex() { elasticsearchTemplate.createIndex(Item.class); }
/** * @Description:删除索引 */ @Test public void testDeleteIndex() { elasticsearchTemplate.deleteIndex(Item.class); } }

先执行创建索引
https://img-blog.csdnimg.cn/2020081410503155.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2MzU3MjQy,size_16,color_FFFFFF,t_70

索引数据操作

此处不多描述,注解已经写明。此处再次贴出原作者经典文章https://blog.csdn.net/chen_2890/article/details/83895646#t7

@RunWith(SpringRunner.class) @SpringBootTest(classes = BootApplication.class) public class ceshiTest { @Autowired private ItemRepository itemRepository; /** * @Description:定义新增方法 */ @Test public void insert() { Item item = new Item(1L, "小米手机7", " 手机", "小米", 3499.00); itemRepository.save(item); }
/** * @Description:定义批量新增方法 */ @Test public void insertList() { List<Item> list = new ArrayList<>(); list.add(new Item(1L, "小米9", "手机", "小米", 3299.00)); list.add(new Item(2L, "华为pro30", "手机", "华为", 3999.00)); list.add(new Item(3L, "一加7", "手机", "一加", 2999.00)); list.add(new Item(4L, "魅族16", "手机", "魅族", 1999.00)); list.add(new Item(5L, "苹果xs", "手机", "苹果", 5099.00)); list.add(new Item(6L, "360pro", "手机", "360", 1099.00)); list.add(new Item(7L, "荣耀V10", "手机", "华为", 899.00 )); // 接收对象集合,实现批量新增 itemRepository.saveAll(list); } /** * @Description:按照价格区间查询 自定义方法 * 自定义方法 Spring Data 的另一个强大功能,是根据方法名称自动实现功能。 比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。 当然,方法名称要符合一定的约定 下边为约定 And findByNameAndPrice Or findByNameOrPrice Is findByName Not findByNameNot Between findByPriceBetween LessThanEqual findByPriceLessThan GreaterThanEqual findByPriceGreaterThan Before findByPriceBefore After findByPriceAfter Like findByNameLike StartingWith findByNameStartingWith EndingWith findByNameEndingWith Contains/Containing findByNameContaining In findByNameIn(Collection<String>names) NotIn findByNameNotIn(Collection<String>names) Near findByStoreNear True findByAvailableTrue False findByAvailableFalse OrderBy findByAvailableTrueOrderByNameDesc * @Author: https://blog.csdn.net/chen_2890 */ @Test public void queryByPriceBetween(){ List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00); for (Item item : list) { System.out.println("item = " + item.getTitle()); } }
@Test public void queryByTitle(){ List<Item> list = this.itemRepository.findByTitle("华为"); for (Item item : list) { System.out.println("item = " + item.getTitle()); } }
@Test public void queryByTitleTo(){ Collection<String> ss = new ArrayList<>(); ss.add("华为"); ss.add("小米"); List<Item> list = this.itemRepository.findByTitleIn(ss); for (Item item : list) { System.out.println("item = " + item.getTitle()); } }
/** * @Description:matchQuery底层采用的是词条匹配查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testMatchQuery(){ // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.matchQuery("title", "华为")); // 搜索,获取结果 Page<Item> items = this.itemRepository.search(queryBuilder.build()); // 总条数 long total = items.getTotalElements(); System.out.println("获取的总条数 = " + total); for (Item item : items) { System.out.println("手机名称是:"+item.getTitle()); } }
/** * @Description: * termQuery:功能更强大,除了匹配字符串以外,还可以匹配 * int/long/double/float/.... * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testTermQuery(){ NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); builder.withQuery(QueryBuilders.termQuery("price",1099)); // 查找 Page<Item> page = this.itemRepository.search(builder.build());
for(Item item:page){ System.out.println("手机是:"+item.getTitle()); } } /** * @Description:布尔查询 多条件查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testBooleanQuery(){ NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery( QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title","华为")) .must(QueryBuilders.matchQuery("brand","华为")) );
// 查找 Page<Item> page = this.itemRepository.search(builder.build()); for(Item item:page){ System.out.println("手机名称是"+item.getTitle()); } }
/** * @Description:布尔查询 多条件查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testBlQuery(){ NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery( QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title","荣耀")) .must(QueryBuilders.matchQuery("title","华为")) );
// 查找 Page<Item> page = this.itemRepository.search(builder.build()); for(Item item:page){ System.out.println("手机名称是"+item.getTitle()); } } /** * @Description:模糊查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testFuzzyQuery(){ NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); builder.withQuery(QueryBuilders.fuzzyQuery("title","一")); Page<Item> page = this.itemRepository.search(builder.build()); for(Item item:page){ System.out.println("手机名称是:"+item.getTitle()); } }
/** * @Description:分页查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void searchByPage(){ // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机")); // 分页: int page = 0; int size = 2; queryBuilder.withPageable(PageRequest.of(page,size)); // 搜索,获取结果 Page<Item> items = this.itemRepository.search(queryBuilder.build()); // 总条数 long total = items.getTotalElements(); System.out.println("总条数 = " + total); // 总页数 System.out.println("总页数 = " + items.getTotalPages()); // 当前页 System.out.println("当前页:" + items.getNumber()); // 每页大小 System.out.println("每页大小:" + items.getSize());
for (Item item : items) { System.out.println(item.getTitle()); } }
/** * @Description:排序查询 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void searchAndSort(){ // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
// 排序 queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
// 搜索,获取结果 Page<Item> items = this.itemRepository.search(queryBuilder.build()); // 总条数 long total = items.getTotalElements(); System.out.println("总条数 = " + total);
for (Item item : items) { System.out.println("手机的价格是:"+item.getTitle()+":"+item.getPrice()); } }
/** * @Description:按照品牌brand进行分组 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testAgg(){ NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 不查询任何结果 queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null)); // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand queryBuilder.addAggregation( AggregationBuilders.terms("brands").field("brand")); // 2、查询,需要把结果强转为AggregatedPage类型 AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.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(bucket.getKeyAsString()); // 3.5、获取桶中的文档数量 System.out.println(bucket.getDocCount()); } }
/** * @Description:嵌套聚合,求平均值 * @Author: https://blog.csdn.net/chen_2890 */ @Test public void testSubAgg(){ NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 不查询任何结果 queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null)); // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand queryBuilder.addAggregation( AggregationBuilders.terms("brands").field("brand") .subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值 ); // 2、查询,需要把结果强转为AggregatedPage类型 AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.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,即品牌名称 3.5、获取桶中的文档数量 System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");
// 3.6.获取子聚合结果: InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg"); System.out.println("平均售价:" + avg.getValue()); } } }

大致的demo就是以上的情况。

问题

但是项目在启动过程中回报一个错误,

Timeout connecting to [localhost/127.0.0.1:9200]

明明已经连接到远端es,但还会出现这个问题。

解决,

spring: data: elasticsearch: cluster-name: docker-cluster cluster-nodes: ip:9300 #配置es节点信息,逗号分隔,如果没有指定,则启动ClientNode properties: path: logs: ./elasticsearch/log #elasticsearch日志存储目录 data: ./elasticsearch/data #elasticsearch数据存储目录 elasticsearch: rest: uris: ["ip:9200"]

即可。

评论