SpringBoot Data操作ES
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
编写yml配置
- spring-data(2~3.x版本配置)
spring:
data:
elasticsearch:
cluster-nodes: 172.16.251.142:9300
- spring-data(新版本推荐配置) RestHighLevelClient rest客户端 ElasticSearchRespositoy接口
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("192.168.202.200:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
操作:
@Autowired
private RestHighLevelClient restHighLevelClient;//复杂查询使用 高亮查询 指定条件查询 transportClient
//添加文档
@Test
public void testAddIndex() throws IOException {
IndexRequest indexRequest = new IndexRequest("ems","emp","12");
indexRequest.source("{\"name\":\"小黑\",\"age\":23}", XContentType.JSON);
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.status());
}
//删除文档
@Test
public void testDeleteIndex() throws IOException {
//参数1: 索引 参数2:类型 参数3:删除id
DeleteRequest deleteRequest = new DeleteRequest("ems","emp","cO78FnMBpzP5KMxRDdbD");
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
//更新文档
@Test
public void testUpdate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("ems","emp","12");
updateRequest.doc("{\"name\":\"张三\",\"age\":23}",XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
//批量更新
@Test
public void testBulk() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
//添加
IndexRequest request = new IndexRequest("ems","emp","11");
request.source("{\"name\":\"李四\",\"age\":23}",XContentType.JSON);
//删除
//修改
bulkRequest.add(request);
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
BulkItemResponse[] items = bulkResponse.getItems();
for (BulkItemResponse item : items) {
System.out.println(item.status());
}
}
//查询所有
@Test
public void testQueryAll() throws IOException {
SearchRequest searchRequest = new SearchRequest("ems");
//创建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查询所有
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.types("emp").source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
@Test
public void testSearch() throws IOException {
//创建搜索对象
SearchRequest searchRequest = new SearchRequest("ems");
//搜索构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery())//执行查询条件
.from(0)//起始条数
.size(20)//每页展示记录
.postFilter(QueryBuilders.matchAllQuery()) //过滤条件
.sort("age", SortOrder.DESC)//排序
.highlighter(new HighlightBuilder().field("*").requireFieldMatch(false));//高亮
//创建搜索请求
searchRequest.types("emp").source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件的文档总数: "+searchResponse.getHits().getTotalHits());
System.out.println("符合条件的文档最大得分: "+searchResponse.getHits().getMaxScore());
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsMap());
}
}
注:RestHighLevelClient 在复杂查询时使用,比如高亮查询,多条件查询。
ES提供面向对象的接口ElasticsearchRepository,提供系列CRUD方法
编写entity
@Document(indexName = "dangdang",type = "book")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
@Id
private String id;
@Field(type = FieldType.Text,analyzer ="ik_max_word")
private String name;
@Field(type = FieldType.Date)
@JsonFormat(pattern="yyyy-MM-dd")
private Date createDate;
@Field(type = FieldType.Keyword)
private String author;
@Field(type = FieldType.Text,analyzer ="ik_max_word")
private String content;
}
@Document
: 代表一个文档记录
indexName
: 用来指定索引名称
type
: 用来指定索引类型
@Id
: 用来将对象中id和ES中_id映射
@Field
: 用来指定ES中的字段对应Mapping
type
: 用来指定ES中存储类型
analyzer
: 用来指定使用哪种分词器
编写BookRepository
public interface BookRepository extends ElasticsearchRepository<Book,String> {
}
索引or更新一条记录
NOTE:这种方式根据实体类中中配置自动在ES创建索引,类型以及映射
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class TestSpringBootDataEs {
@Autowired
private BookRepository bookRespistory;
/**
* 添加索引和更新索引 id 存在更新 不存在添加
*/
@Test
public void testSaveOrUpdate(){
Book book = new Book();
book.setId("21");
book.setName("小陈");
book.setCreateDate(new Date());
book.setAuthor("李白");
book.setContent("这是中国的好人,这真的是一个很好的人,李白很狂");
bookRespistory.save(book);
}
}
删除一条记录
/**
* 删除一条索引
*/
@Test
public void testDelete(){
Book book = new Book();
book.setId("21");
bookRespistory.delete(book);
}
查询
/**
* 查询所有
*/
@Test
public void testFindAll(){
Iterable<Book> books = bookRespistory.findAll();
for (Book book : books) {
System.out.println(book);
}
}
/**
* 查询一个
*/
@Test
public void testFindOne(){
Optional<Book> byId = bookRespistory.findById("21");
System.out.println(byId.get());
}
查询排序
/**
* 排序查询
*/
@Test
public void testFindAllOrder(){
Iterable<Book> books = bookRespistory.findAll(Sort.by(Sort.Order.asc("createDate")));
books.forEach(book -> System.out.println(book) );
}
自定义基本查询
关键字 样例 es中的实现
| 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`<br>`(Collection<String>names)` | `{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}` |
| `NotIn` | `findByNameNotIn`<br/>`(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`<br>`TrueOrderByNameDesc` | `{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}` |
#es会自动帮我们实现方法就,使用上面的关键字
public interface BookRepository extends ElasticsearchRepository<Book,String> {
//根据作者查询
List<Book> findByAuthor(String keyword);
//根据内容查询
List<Book> findByContent(String keyword);
//根据内容和名字查
List<Book> findByNameAndContent(String name,String content);
//根据内容或名称查询
List<Book> findByNameOrContent(String name,String content);
//范围查询
List<Book> findByPriceBetween(Double start,Double end);
//查询名字以xx开始的
List<Book> findByNameStartingWith(String name);
//查询某个字段值是否为false
List<Book> findByNameFalse();
//.......
}
实现复杂查询
分页查询并排序
@Test
public void testSearchPage() throws IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0).size(2).sort("age", SortOrder.DESC).query(QueryBuilders.matchAllQuery());
searchRequest.indices("ems").types("emp").source(sourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = search.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
高亮查询
@Test
public void testSearchHig() throws IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("content").requireFieldMatch(false).preTags("<span style='color:red;'>").postTags("</span>");
sourceBuilder.from(0).size(2).sort("age", SortOrder.DESC).highlighter(highlightBuilder).query(QueryBuilders.termQuery("content","框架"));
searchRequest.indices("ems").types("emp").source(sourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = search.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
highlightFields.forEach((k,v)-> System.out.println("key: "+k + " value: "+v.fragments()[0]));
}
}