官方文檔:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.5/java-rest-high-search.html (這個版本是6.5的)根據自己的來選擇
- index可以類比為MySQL中的表這個概念,他是一類型數據存儲的集合。
- document其實就是index這個集合里面單條數據的一種稱呼,這個概念和MySQL中的行記錄比較類似。
- type是這個代表document屬於index中的哪個類別(type),一個index通常會划分為多個type,邏輯上對index中有些許不同的幾類數據進行分類:因為一批相同的數據,可能有很多相同的fields,但是還是可能會有一些輕微的不同,可能會有少數fields是不一樣的,舉個例子,就比如說,商品,可能划分為電子商品,生鮮商品,日化商品,等等。
引入依賴
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.8.0</version> </dependency> <!-- elasticsearch的客戶端 --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.8.0</version> </dependency> <!-- elasticsearch依賴2.x的log4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.8.2</version> </dependency> <!-- 阿里JSON解析器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
yml文件
#elasticsearch
esHostName: 192.168.1.25
esPort: 9200
ContentModel.java 根據自己的實際業務來
import lombok.Data; import lombok.ToString; import lombok.experimental.Accessors; /** * es存放實體類 */ @Data @Accessors(chain = true) @ToString public class ContentModel { private static final long serialVersionUID = 6320548148250372657L; private Integer contentId; private String title; }
配置類
EsConfig.java
import org.apache.http.HttpHost; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author yvioo。 */ @Configuration public class EsConfig { @Value("${esHostName}") private String esHostName; @Value("${esPort}") private Integer esPort; public static final RequestOptions COMMON_OPTIONS; static { RequestOptions.Builder builder=RequestOptions.DEFAULT.toBuilder(); COMMON_OPTIONS=builder.build(); } @Bean public RestHighLevelClient esRestClient(){ RestClientBuilder builder = RestClient.builder(new HttpHost(esHostName, esPort, "http")); RestHighLevelClient client=new RestHighLevelClient(builder); return client; } }
常量
EsConstant.java 可以不用
/** * @author yvioo。 */ public class EsConstant { public static final String CONTENT_INDEX="索引名稱"; public static final String CONTENT_TYPE="類型"; }
工具類
EsService.java
import com.alibaba.fastjson.JSON; import com.example.es.elasticsearch.entity.ContentModel; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * es操作類 * * @author 洪。 */ @Slf4j @Service public class EsService { @Resource private RestHighLevelClient restHighLevelClient; /** * 批量插入文檔數據 * @return 返回true 表示有錯誤 */ public boolean batchEsContent(List<ContentModel> contentModelList) throws IOException { BulkRequest bulkRequest = new BulkRequest(); List<Integer> delIds=new LinkedList<>(); for (ContentModel model : contentModelList) { IndexRequest indexRequest = new IndexRequest(EsConstant.CONTENT_INDEX).type(EsConstant.CONTENT_TYPE); indexRequest.id(model.getContentId().toString()); String s = JSON.toJSONString(model); indexRequest.source(s, XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, EsConfig.COMMON_OPTIONS); List<String> collect = Arrays.stream(bulk.getItems()).map(item -> { return item.getId(); }).collect(Collectors.toList()); log.error("內容索引生成:{}", collect); return bulk.hasFailures(); } /** * 判斷是否存在文檔數據 * * @param id 索引的ID * @return * @throws IOException */ public boolean existIndex(Integer id) throws IOException { GetRequest getRequest = new GetRequest( EsConstant.CONTENT_INDEX, id.toString()); getRequest.fetchSourceContext(new FetchSourceContext(false)); getRequest.storedFields("_none_"); return restHighLevelClient.exists(getRequest, EsConfig.COMMON_OPTIONS); } /** * 刪除文檔數據 * @param id * @return * @throws IOException */ public boolean deleteIndex(Integer id) throws IOException { DeleteRequest request = new DeleteRequest( EsConstant.CONTENT_INDEX, id.toString()); DeleteResponse deleteResponse = restHighLevelClient.delete( request, EsConfig.COMMON_OPTIONS); if (deleteResponse.status().getStatus()== RestStatus.OK.getStatus()){ return true; } return false; } /** * 批量刪除索引 * @param ids * @return 返回true 表示有錯誤 * @throws IOException */ public boolean deleteBatchIndex(List<Integer> ids) throws IOException { // 批量刪除數據 BulkRequest request = new BulkRequest(); ids.forEach(s->{ request.add(new DeleteRequest().index(EsConstant.CONTENT_INDEX).type(EsConstant.CONTENT_TYPE).id(s.toString())); }); BulkResponse response = restHighLevelClient.bulk(request, EsConfig.COMMON_OPTIONS); return response.hasFailures(); } /** * 更新文檔數據 * @param contentModel * @return * @throws IOException */ public boolean updateIndex(ContentModel contentModel) throws IOException { // 修改數據 UpdateRequest request = new UpdateRequest(); request.index(EsConstant.CONTENT_INDEX).id(contentModel.getContentId().toString()); String s = JSON.toJSONString(contentModel); request.doc(s, XContentType.JSON); UpdateResponse updateResponse = restHighLevelClient.update(request, EsConfig.COMMON_OPTIONS); if (updateResponse.status().getStatus()== RestStatus.OK.getStatus()){ return true; } return false; } }
使用直接注入 EsService 然后調用里面的方法即可
由於每種業務查詢的寫法都不一定,沒有通用性 所以這里只提供一些基礎的方法
官網地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high-search.html
基礎的查詢所有的demo
@Resource private RestHighLevelClient restHighLevelClient;
//創建檢索請求 SearchRequest searchRequest = new SearchRequest("這里可以直接指定索引"); //創建檢索條件 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //這個表示查詢所有 searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchRequest.source(searchSourceBuilder); //執行檢索 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHits searchHits = searchResponse.getHits(); //所有條數 long totalHits = searchHits.getTotalHits(); //遍歷結果 for (SearchHit hit : searchHits) { ContentDto content = new ContentDto(); Map<String, Object> sourceAsMap = hit.getSourceAsMap(); //取出對應的結果 String documentTitle = (String) sourceAsMap.get("title"); }
數據量超過一萬條1w就需要加下面這個才會反正正確的頁碼
searchSourceBuilder.trackTotalHits(true);
但是也可以報錯 查詢報錯參考: Elasticsearch(es)查詢報錯:Result window is too large, from + size must be less than or equal to: [10000] but was [20000
精確查詢匹配多個字段
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery() .must(QueryBuilders.termQuery("db.database", "庫")) .must(QueryBuilders.termQuery("db.table", "表")) .must(QueryBuilders.termQuery("addressId", "地址"));
模糊查詢
BoolQueryBuilder builder = QueryBuilders.boolQuery(); // 手機號模糊查詢 String phone = bo.getPhone(); if (StringUtils.isNotBlank(phone)) { phone = "*"+phone+"*"; BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); WildcardQueryBuilder phoneBuilder = QueryBuilders.wildcardQuery("phone", phone); WildcardQueryBuilder mobileBuilder = QueryBuilders.wildcardQuery("mobile", phone); boolQueryBuilder.should(phoneBuilder); boolQueryBuilder.should(mobileeBuilder); builder.must(boolQueryBuilder); }
聚合函數-統計某個字段的值
// 構建搜索請求 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.aggregation(AggregationBuilders.sum("field_sum").field("your_field"));
使用 sum
聚合來計算指定字段的總和。將 your_field
替換為你實際想要統計的字段名。
取值
// 獲取聚合結果 Sum sumAgg = response.getAggregations().get("field_sum"); double sumValue = sumAgg.getValue();
下面的field_sum與上面查詢設置的對應
分頁
sourceBuilder.from((query.getPageNo() > 0 ? (query.getPageNo() - 1) : 0) * query.getPageSize());
sourceBuilder.size(query.getPageSize());
數值范圍篩選,大於0
query.must(QueryBuilders.rangeQuery("total").gt(0));