ElasticSearch6.x版本的SpringBoot增删改查操作和ElasticSearch6.x版本的过滤查询

一、教学讲解视频

教学讲解视频地址:视频地址

二、SpringBoot操作ElasticSearch前期准备工作

1.先在pom.xml里面引入依赖。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2.然后在SpringBoot项目中增加以下配置。

这里我是用HTTP的方式进行连接,端口是9200。如果你们是用TCP方式进行连接的话,端口记得改成9300。

@Configuration
public class ESRestClientConfig extends AbstractElasticsearchConfiguration {
    
    

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
    
    
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("127.0.0.1:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

}

3.编写要创建索引和类型的实体。
记得生成getter和setter方法哦。
@Document: 代表一个文档记录,使用此注解项目启动后自动创建索引和类型

indexName: 用来指定索引名称

type: 用来指定索引类型

@Id: 用来将对象中id和ES中_id映射

@Field: 用来指定ES中的字段对应Mapping

type: 用来指定ES中存储类型

analyzer: 用来指定使用哪种分词器

@Document(indexName = "online_house_achieve", type = "house")
public class House {
    
    

	@Id
    private Long id; //房屋id

    private String coverPhoto; //封面图片

    private String ownerShip; //房本图片

    private BigDecimal money; //租金(元/月)

//    @Field(type = FieldType.Text, analyzer ="ik_max_word")
    private String houseType; //户型

    private BigDecimal area; //面积

//    @Field(type = FieldType.Keyword)
    private String orientation; //朝向

//    @Field(type = FieldType.Text, analyzer ="ik_max_word")
    private String floor; //楼层

    private String renovation; //装修

    private Integer category; //房屋出售种类

//    @Field(type = FieldType.Text, analyzer ="ik_max_word")
    private String location; //房屋位置

//    @Field(type = FieldType.Text, analyzer ="ik_max_word")
    private String info; //房屋简介

//    @Field(type = FieldType.Text, analyzer ="ik_max_word")
    private String details; //房屋详情

    private Long userId; //房屋所属中介id

//    @Field(type = FieldType.Object)
    private User user; //房屋所属中介

    private Date createTime; //创建时间

//    @Field(type = FieldType.Date)
    private Date updateTime; //更新时间

    private Integer state; //房屋状态

4.编写Repository接口。

public interface HouseRepository extends ElasticsearchRepository<House,String> {
    
    

}

5.启动类上加上Repository接口扫描。

@SpringBootApplication
@EnableElasticsearchRepositories(basePackages = "com.wx.programmer.repository")
public class OnlineHouseAchieve
{
    
    
    public static void main( String[] args )
    {
    
    
        SpringApplication.run(OnlineHouseAchieve.class, args);
    }
}

这样前期准备工作就完成了~

三、SpringBoot增删改查ElasticSearch

1.新增修改

Tips:如果传id的话,id在ES中存在则修改更新数据,如果id在ES中不存在,则新增数据。如果不传id,则新增一条_id随机的数据。

使用spring-data-elasticsearch完成新增修改操作:

  @Test
  public void testSaveOrUpdate() {
    
    
	  House house = new House();
	  house.setId(1L);
	  house.setUpdateTime(new Date());
	  house.setInfo("中装一室一厅,楼层好,采光足,稀缺房源");
	  house.setDetails("半径200米内有:工商银行,建设银行,农业银行,邮电局,中国电信,民航总医院,朝阳区第二医院,小庄医院,易出莲花,华堂商场,京客隆,法宝超市,苏宁电器,国美电器,郭林家常菜,肯德基,麦当劳,必胜客等多家餐厅,北京纺织技术学校,甘露园小学。");
	  houseRepository.save(house);
  }

使用RestHighLevelClient完成新增修改操作:

IndexRequest request = new IndexRequest("online_house_achieve", "house");
request.id("1");
request.source(JSONObject.toJSONString(house), XContentType.JSON);
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
logger.info("操作结果:" + response.getResult());

2.删除

使用spring-data-elasticsearch完成删除操作:

 @Test
 public void testDelete(){
    
    
      House house = new House();
      house.setId(1L);
      houseRepository.delete(house);
 }

使用RestHighLevelClient完成删除操作:

 DeleteRequest request = new DeleteRequest("online_house_achieve", "house", "1");
 DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
 logger.info("操作结果:" + response.getResult());

3.查询

使用spring-data-elasticsearch完成查询操作:

Keyword Sample Elasticsearch Query String
And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
In findByNameIn
(Collection<String>names)
{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotIn findByNameNotIn
(Collection<String>names)
{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
Near findByStoreNear Not Supported Yet !
True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
OrderBy findByAvailable
TrueOrderByNameDesc
{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

spring-data-elasticsearch操作方式有很多种,我们这里举例演示一种,其他的根据上面表格内容举一反三~

1.根据houseType字段和orientation字段查询数据:

public interface HouseRepository extends ElasticsearchRepository<House,String> {
    
    
    // 根据户型和朝向查询
    List<House> findByHouseTypeAndOrientation(String houseType, String orientation);
}
 @Test
 public void testESSearch(){
    
    
     List<House> result = houseRepository.findByHouseTypeAndOrientation("两室一厅一卫", "南");
     logger.info("查询结果:{}", JSONObject.toJSONString(result));
 }

使用RestHighLevelClient完成查询操作:
RestHighLevelClient操作方式有很多种,我们这里举例演示几种,其他的根据上面表格内容举一反三~
1.根据id降序排序,然后获取前两个数据。

 SearchRequest searchRequest = new SearchRequest();
 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
 sourceBuilder.from(0).size(2).sort("id", SortOrder.DESC).query(QueryBuilders.matchAllQuery());
 searchRequest.indices("online_house_achieve").types("house").source(sourceBuilder);
 SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
 SearchHit[] hits = search.getHits().getHits();
 for (SearchHit hit : hits) {
    
    
     logger.info(hit.getSourceAsString());
 }

2.高亮查询,查询orientation字段值为“南”的文档数据,并高亮展示。

 SearchRequest searchRequest = new SearchRequest();
 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
 HighlightBuilder highlightBuilder =  new HighlightBuilder();
 highlightBuilder.field("orientation").preTags("<span style='color:red;'>").postTags("</span>");
 sourceBuilder.highlighter(highlightBuilder).
         query(QueryBuilders.termQuery("orientation","南"));
 searchRequest.indices("online_house_achieve").types("house").source(sourceBuilder);
 SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
 SearchHit[] hits = search.getHits().getHits();
 for (SearchHit hit : hits) {
    
    
     logger.info(hit.getSourceAsString());
     Map<String, HighlightField> highlightFields = hit.getHighlightFields();
     highlightFields.forEach((k,v)-> logger.info("key: "+k + " value: "+v.fragments()[0]));
 }

3.布尔查询,查询出money字段值在2500~2700之间的数据或者category字段值为2的文档数据:

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
RangeQueryBuilder rangeQueryBuilder = QueryBuilders
        .rangeQuery("money").from(2500).to(2700);
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("category", 2);
boolQueryBuilder.should(termQueryBuilder).should(rangeQueryBuilder);
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.indices("online_house_achieve").types("house").source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = search.getHits().getHits();
for (SearchHit hit : hits) {
    
    
    logger.info(hit.getSourceAsString());
}

4.布尔查询,将上面代码改造,只查询出money字段值在2500~2700之间的数据:

boolQueryBuilder.should(termQueryBuilder).must(rangeQueryBuilder);

5.布尔查询,将上面代码改造,只查询出category字段值不为2的并且money字段值在2500~2700之间的文档数据。

boolQueryBuilder.mustNot(termQueryBuilder).must(rangeQueryBuilder);

6.过滤查询,先过滤出category字段值为2的数据,然后从过滤出的数据中查找orientation字段值为"东"的数据。

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders
        .termQuery("orientation", "东");
boolQueryBuilder.must(termQueryBuilder).filter(QueryBuilders.termQuery("category", 2));
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.indices("online_house_achieve").types("house").source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = search.getHits().getHits();
for (SearchHit hit : hits) {
    
    
    logger.info(hit.getSourceAsString());
}

四、ElasticSearch中的过滤查询

1.概念介绍

其实准确来说,ES中的查询操作分为2种: 查询(query)过滤(filter)查询即是之前提到的query查询,它 (查询)默认会计算每个返回文档的得分,然后根据得分排序而过滤(filter)只会筛选出符合的文档,并不计算得分,且它可以缓存文档 。所以,单从性能考虑,过滤比查询更快

有关查询的用法,请浏览博客:ElasticSearch6.x版本概念介绍及Kibana操作的增删改查常用API

换句话说,过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时, 应先使用过滤操作过滤数据, 然后使用查询匹配数据。

具体流程看下图:
在这里插入图片描述

2.过滤语法

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "match_all": {
    
    }}
      ],
      "filter": {
    
    
        "range": {
    
    
          "id": {
    
    
            "gte": 5,
            "lte": 8
          }
        }
      }
    }
  }
}

在执行filter和query时,先执行filter在执行query。
ElasticSearch会自动缓存经常使用的过滤器,以加快性能。

3.常见的过滤器类型

① term filter

先过滤出category字段为2的文档数据,然后再从过滤出来的文档数据中查询orientation字段为 “东” 的文档数据:

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "term": {
    
    
          "orientation": {
    
    
            "value": "东"
          }
        }}
      ],
      "filter": {
    
    
        "term": {
    
    
          "category": 2
        }
      }
    }
  }
}

② terms filter

先过滤出category字段为1或2的文档数据,然后再从过滤出来的文档数据中查询orientation字段为 “东” 的文档数据:

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "term": {
    
    
          "orientation": {
    
    
            "value": "东"
          }
        }}
      ],
      "filter": {
    
    
        "terms": {
    
    
          "category":[
              1,2
          ]
        }
      }
    }
  }
}

③ ranage filter

先过滤出id字段值在5~8之间的文档数据,然后再从过滤出来的文档数据中查询orientation字段为 “东” 的文档数据:

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "term": {
    
    
          "orientation": {
    
    
            "value": "东"
          }
        }}
      ],
      "filter": {
    
    
        "range": {
    
    
          "id": {
    
    
            "gte": 5,
            "lte": 8
          }
        }
      }
    }
  }
}

④ exists filter

先过滤出id字段存在的文档数据,然后再从过滤出来的文档数据中查询orientation字段为 “东” 的文档数据:

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "term": {
    
    
          "orientation": {
    
    
            "value": "东"
          }
        }}
      ],
      "filter": {
    
    
        "exists": {
    
    
          "field": "id"
        }
      }
    }
  }
}

⑤ ids filter

先过滤出id字段值为5或8的文档数据,然后再从过滤出来的文档数据中查询orientation字段为 “东” 的文档数据:

GET /online_house_achieve/house/_search
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    "term": {
    
    
          "orientation": {
    
    
            "value": "东"
          }
        }}
      ],
      "filter": {
    
    
        "ids": {
    
    
          "values": [5, 8]
        }
      }
    }
  }
}

猜你喜欢

转载自blog.csdn.net/dgfdhgghd/article/details/128511077
今日推荐