PUT /order_auto/
{
"settings":{
"index":{
"number_of_shards" : "3",
"number_of_replicas" : "0"
}
}
}
PUT /order_auto/_doc/_mappings?include_type_name=true
{
"properties": {
"id": {
"type": "keyword"
},
"orderNo": {
"type": "keyword"
},
"status": {
"type": "text"
},
"pushed": {
"type": "keyword"
},
"requestDecisionNo": {
"type": "keyword"
},
"initParam": {
"type": "keyword"
},
"customerId": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"channelId": {
"type": "keyword"
},
"channelName": {
"type": "keyword"
},
"idCard": {
"type": "keyword"
},
"phone": {
"type": "text"
},
"operateType": {
"type": "keyword"
},
"requestDecisionParam": {
"type": "keyword"
},
"requestManualParam": {
"type": "keyword"
},
"manualResult": {
"type": "keyword"
},
"decisionResult": {
"type": "keyword"
},
"sceneNo": {
"type": "keyword"
},
"storeFlag": {
"type": "keyword"
},
"artificialFlag": {
"type": "keyword"
},
"manualPushed": {
"type": "keyword"
},
"branchInfo": {
"type": "keyword"
},
"createTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"updateTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
上面,新建es索引。
es搜索
package com.mark.order.web.base.configures.es;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mark.order.domain.consts.Const;
import com.mark.order.domain.dto.OrderEs;
import com.mark.order.domain.enums.order.OrderStateEnum;
import com.mark.order.domain.enums.order.OrderStateVOEnum;
import com.mark.order.domain.vo.orderquery.OrderQueryReqParam;
import com.mark.order.domain.vo.orderquery.OrderQueryRespVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author : mark
* @desc : es工具类
* @since : 2021/8/27 15:33
*/
@Slf4j
@Component
public class ElasticSearchOperation {
@Resource
EsConfig esConfig;
private final RestHighLevelClient restHighLevelClient;
public ElasticSearchOperation(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
}
/**
* 新增数据到es
*
* @param indexName 索引名称
* @param data 对象
* @param indexId 索引id
*/
public boolean add(String indexName, Object data, String indexId) {
if (indexName == null || data == null || indexId == null) {
return false;
}
IndexRequest request = new IndexRequest(indexName);
request.id(indexId);
request.source(JSONObject.toJSONString(data), XContentType.JSON);
try {
IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
if (indexResponse == null) {
return false;
}
log.info("写入es成功,风控订单号:{}", indexId);
return (indexResponse.getResult() == DocWriteResponse.Result.CREATED
|| indexResponse.getResult() == DocWriteResponse.Result.UPDATED);
} catch (Throwable e) {
log.error(
"ElasticSearchGateway#add's params indexName={} and data={} and indexId = {} and Exception Occurred:",
indexName, JSONObject.toJSONString(data), indexId, e);
}
return false;
}
/**
* 更新数据
*/
public Boolean update(OrderEs orderEs) {
log.info("更新订单到es请求参数:{}", JSON.toJSONString(orderEs));
UpdateRequest updateRequest = new UpdateRequest(esConfig.getIndexName(), String.valueOf(orderEs.getId()));
updateRequest.retryOnConflict(3);
updateRequest.doc(JSON.toJSONString(orderEs), XContentType.JSON);
// 操作ES
UpdateResponse updateResponse = null;
try {
log.info("es更新数据,rq:{}", JSON.toJSONString(updateRequest));
updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("es订单更新失败", e);
}
return updateResponse != null && updateResponse.status().getStatus() == 200;
}
/**
* 查询es
*/
public Map<String, Object> search(OrderQueryReqParam entity) throws IOException {
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
String status = entity.getStatus();
if (StrUtil.isNotEmpty(status)) {
//待决策和初始化
if (String.valueOf(OrderStateVOEnum.待审核.getCode()).equals(status)) {
TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("status",
OrderStateEnum.待决策.getCode(), String.valueOf(OrderStateEnum.初始化.getCode()));
boolBuilder.must(termsQuery);
}
//待人工审核,人工审核中
if (String.valueOf(OrderStateVOEnum.电核中.getCode()).equals(status)) {
TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("status",
OrderStateEnum.待人工审核.getCode(), String.valueOf(OrderStateEnum.人工审核中.getCode()));
boolBuilder.must(termsQuery);
}
//机核挂起
MatchQueryBuilder matchQueryBuilder = null;
if (String.valueOf(OrderStateVOEnum.机核挂起.getCode()).equals(status)) {
matchQueryBuilder = QueryBuilders.matchQuery("status",
OrderStateEnum.挂起.getCode());
boolBuilder.must(matchQueryBuilder);
}
//外部取消
if (String.valueOf(OrderStateVOEnum.外部取消.getCode()).equals(status)) {
matchQueryBuilder = QueryBuilders.matchQuery("status",
OrderStateEnum.已取消.getCode());
}
if (String.valueOf(OrderStateVOEnum.审核通过.getCode()).equals(status)) {
matchQueryBuilder = QueryBuilders.matchQuery("status", status);
}
if (String.valueOf(OrderStateVOEnum.审核拒绝.getCode()).equals(status)) {
matchQueryBuilder = QueryBuilders.matchQuery("status", status);
}
boolBuilder.must(matchQueryBuilder);
}
if (Const.STORE_ORDER.equals(entity.getStoreFlag())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("storeFlag", entity.getStoreFlag());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getOrderNo())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("orderNo", entity.getOrderNo());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getCustomerId())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("customerId", entity.getCustomerId());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getChannelId())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("channelId", entity.getChannelId());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getFkOrderNo())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("id", entity.getFkOrderNo());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getBranchInfo())) {
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("branchInfo", "*" + entity.getBranchInfo() + "*");
boolBuilder.must(wildcardQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getDecisionResult())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("decisionResult", entity.getDecisionResult());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getArtificialFlag())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("artificialFlag", entity.getArtificialFlag());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getSceneCode())) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("sceneCode", entity.getSceneCode());
boolBuilder.must(matchQueryBuilder);
}
if (StrUtil.isNotEmpty(entity.getStartTime()) && StrUtil.isNotEmpty(entity.getEndTime())) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("createTime");
rangeQueryBuilder.gte(entity.getStartTime());
rangeQueryBuilder.lte(entity.getEndTime());
boolBuilder.must(rangeQueryBuilder);
}
sourceBuilder.query(boolBuilder);
sourceBuilder.from((entity.getPageNum() - 1) * entity.getPageSize());
sourceBuilder.size(entity.getPageSize());
sourceBuilder.timeout(new TimeValue(20, TimeUnit.SECONDS));
String[] fields = {"id", "orderNo", "status", "requestDecisionNo", "customerId", "name", "channelId", "channelName",
"idCard", "phone", "operateType", "requestDecisionTime", "decisionResult", "sceneNo", "sceneName",
"createTime", "updateTime", "artificialFlag", "manualPushed", "storeFlag", "branchInfo"};
sourceBuilder.fetchSource(fields, new String[]{});
SearchRequest searchRequest = new SearchRequest(esConfig.getIndexName());
//按照更新时间排序
FieldSortBuilder fsb = SortBuilders.fieldSort("createTime");
fsb.order(SortOrder.DESC);
sourceBuilder.sort(fsb);
sourceBuilder.query(boolBuilder);
sourceBuilder.trackTotalHits(true);
searchRequest.source(sourceBuilder);
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
List<Map<String, Object>> result = setSearchResponse(response);
log.info("查询响应:{}", result);
List<OrderQueryRespVO> list = new ArrayList<>();
for (Map<String, Object> stringObjectMap : result) {
OrderQueryRespVO vo = MapToBean(stringObjectMap, OrderQueryRespVO.class);
//做状态映射
vo.setStatusValue(cast(vo.getStatus()));
list.add(vo);
}
Map<String, Object> map = new HashMap<>(4);
map.put("list", list);
map.put("total", response.getHits().getTotalHits().value);
return map;
}
/**
* 查询结果转map
*/
private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse) {
ArrayList<Map<String, Object>> list = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
list.add(sourceAsMap);
}
return list;
}
/**
* map转对象
*/
public static <T> T MapToBean(Map<String, ?> map, Class<T> clazz) {
try {
T bean = clazz.newInstance();
BeanUtils.populate(bean, map);
return bean;
} catch (Exception e) {
log.error("map转对象异常");
}
return null;
}
/**
* @param status 任务驱动使用的状态
* @return 展示给页面的状态
*/
public String cast(Integer status) {
//待审核
if (OrderStateEnum.初始化.getCode().equals(status) ||
OrderStateEnum.待决策.getCode().equals(status)) {
return OrderStateVOEnum.待审核.getValue();
}
//机核中
if (OrderStateEnum.决策中.getCode().equals(status)) {
return OrderStateVOEnum.机核中.getValue();
}
//电核中
if (OrderStateEnum.待人工审核.getCode().equals(status) ||
OrderStateEnum.人工审核中.getCode().equals(status)) {
return OrderStateVOEnum.电核中.getValue();
}
//审核通过
if (OrderStateEnum.审核通过.getCode().equals(status)) {
return OrderStateVOEnum.审核通过.getValue();
}
//审核拒绝
if (OrderStateEnum.审核拒绝.getCode().equals(status)) {
return OrderStateVOEnum.审核拒绝.getValue();
}
//外部取消
if (OrderStateEnum.已取消.getCode().equals(status)) {
return OrderStateVOEnum.外部取消.getValue();
}
return OrderStateVOEnum.机核挂起.getValue();
}
}
组合查询
现实的查询需求从来都没有那么简单;它们需要在多个字段上查询多种多样的文本,并且根据一系列的标准来过滤。为了构建类似的高级查询,你需要一种能够将多查询组合成单一查询的查询方法。
你可以用 bool 查询来实现你的需求。这种查询将多查询组合在一起,成为用户自己想要的布尔查询(Bool)。
它接收以下参数:
1.must
文档 必须 匹配这些条件才能被包含进来。
相当于sql中的 and
2.must_not
文档 必须不 匹配这些条件才能被包含进来。
相当于sql中的 not
3.should
如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
相当于sql中的or
4.filter
必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
每一个子查询都独自地计算文档的相关性得分。一旦他们的得分被计算出来, bool 查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分score。\
示例:下面的查询用于查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
java
BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery();
defaultQueryBuilder.must(QueryBuilders.matchQuery("title", "how to make millions"))
.mustNot(QueryBuilders.matchQuery("tag", "span"))
.should(QueryBuilders.matchQuery("tag", "starred"))
.should(QueryBuilders.rangeQuery("date").gte("2014-01-01"));
filter用法
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"range": { "date": { "gte": "2014-01-01" }}
}
}
}
filter中的条件不参与评分score排序