반복 ElasticSearch 중첩 조회
                                            
 9453 단어  ElasticSearch
                    
0 개요
실제 업무에서 우리는 자주 and와 or, 그리고 상관없는 플러그인 조회 방식을 만날 수 있다. 본고는 귀속 방식을 이용하여 이런 상대적으로 복잡한 플러그인 조회를 실현한다.
1 인스턴스 분석
아래와 같이 사용자 테이블에name이 빨간색이고 그의 나이는 10 이상이거나 15 이상이어야 합니다
select * from user where name=' ' and  (age=10 or  age >15)
  or 쓰기 인스턴스 조회
select * from user where objectType=13 and  (userId=1234 or  userType =2 )
query  
{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {
                        "objectType": 13
                    }
                },
                {
                    "bool": {
                        "should": [
                            {
                                "bool": {
                                    "must": [
                                        {
                                            "term": {
                                                "userId": 1234
                                            }
                                        }
                                    ]
                                }
                            },
                            {
                                "bool": {
                                    "must": [
                                        {
                                            "term": {
                                                "userType": 2
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}
  //JSON 내보내기
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class QueryBuilderJSON {
  
  public static void main(String[] args) {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    final BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
    queryBuilder.must(QueryBuilders.termQuery("objectType", 13));
    final BoolQueryBuilder and = QueryBuilders.boolQuery();
    queryBuilder.must(and);
    final BoolQueryBuilder or1 = QueryBuilders.boolQuery();
    final BoolQueryBuilder or2 = QueryBuilders.boolQuery();
    and.should(or1);
    and.should(or2);
    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("created").from(12);
    or1.must(QueryBuilders.termQuery("useType", 1));
    or2.filter(rangeQueryBuilder);
    System.out.print(searchSourceBuilder.query(queryBuilder).toString());
  }
}
  2 실현
ElasticSearch의 기본 조회 방식은 제가 이전에 쓴 ElasticSearch 데이터 조회를 참고할 수 있습니다. 이것은 이전에 쓴 코드에 재구성하여 이런 복잡한 플러그인 조회를 더욱 잘 지원합니다.질의 조건 정의(열에 대한 작업)
public class Condition {
  private String fieldName;// 
  private Object fieldValue;// 
  private FieldOperator operator;// 
  public String getFieldName() {
    return fieldName;
  }
  public void setFieldName(String fieldName) {
    this.fieldName = fieldName;
  }
  public Object getFieldValue() {
    return fieldValue;
  }
  public void setFieldValue(Object fieldValue) {
    this.fieldValue = fieldValue;
  }
  public FieldOperator getOperator() {
    return operator;
  }
  public void setOperator(FieldOperator operator) {
    this.operator = operator;
  }
}
  중첩된 쿼리, 하위 쿼리의
public class HybridCondition extends Condition {
  private Connector connector;
  private List subConditions=new ArrayList<>();
  public HybridCondition(Connector connector) {
    this.connector = connector;
  }
  public Connector getConnector() {
    return connector;
  }
  public void setConnector(Connector connector) {
    this.connector = connector;
  }
  public List getSubConditions() {
    return subConditions;
  }
  // 
  public void setSubConditions(
      List subConditions) {
    this.subConditions = subConditions;
  }
  public HybridCondition addCondition(Condition condition) {
    // , 
    if (condition == this) {
      return this;
    }
    subConditions.add(condition);
    return this;
  }
}
     public enum Connector {
  AND("and"),
  OR("or"),
  EMPTY("");
  private String connName;
  Connector(String connName) {
    this.connName = connName;
  }
  public String getConnName() {
    return connName;
  }
  public static boolean isEmpty(Connector conn) {
    return conn == null || conn == EMPTY;
  }
}
  반복적으로 이런 플러그인 조회를 실현하다
@Component
public class ElasticSearchQueryBuilder {
  @Autowired
  private FieldObjectHandlerRegistry registry;
  private final static int MAX_DEPTH=200;
  public ESSearchRequest buildQuery(QueryContext queryContext) {
    final BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
    final String esIndex = queryContext.getIndex();
    // 
    buildQuery(queryBuilder, queryContext.getFieldObjects());
    ESSearchRequest esSearchRequest = queryContext.getEsClient().buildingESSearchRequest()
        .setIndices(esIndex)
        .setTypes(queryContext.getType())
        .setSize(queryContext.getPageSize())
        .setFrom(queryContext.getOffset())
        .setQuery(queryBuilder);
    // 
    setSearchRequestBuilderSort(esSearchRequest, queryContext);
    return esSearchRequest;
  }
  private void setSearchRequestBuilderSort(ESSearchRequest esSearchRequest,
      QueryContext queryContext) {
    if (queryContext.getSortRules() == null) {
      return;
    }
    for (SortRule sortRule : queryContext.getSortRules()) {
      if (ContentConstant.SORT_FIELD.contains(sortRule.getField())) {
        esSearchRequest.addSort(sortRule.getField(), sortOrder(sortRule.getSort()));
      }
    }
  }
  private SortOrder sortOrder(final String order) {
    return "asc".equalsIgnoreCase(order) ? SortOrder.ASC : SortOrder.DESC;
  }
  private void buildQuery(BoolQueryBuilder queryBuilder, List conditions) {
    if (CollectionUtils.isEmpty(conditions)) {
      return;
    }
    for (Condition object : conditions) {
      buildQueryBuilder(object,queryBuilder,0);
    }
  }
  private void buildQueryBuilder(Condition queryCondition,BoolQueryBuilder queryBuilder,int depth) {
    if (depth > MAX_DEPTH) {
      // , , 
      throw new IllegalArgumentException("query condition loop depth is too big.");
    }
    if (queryCondition instanceof HybridCondition) {
      final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
      HybridCondition hybridCondition = (HybridCondition) queryCondition;
      if (Connector.AND.equals(hybridCondition.getConnector())) {
        for (Condition condition : hybridCondition.getSubConditions()) {
          buildQueryBuilder(condition,boolQueryBuilder,depth+1);
        }
        queryBuilder.must(boolQueryBuilder);
      }else if (Connector.OR.equals(hybridCondition.getConnector())) {
        for (Condition condition : hybridCondition.getSubConditions()) {
          buildQueryBuilder(condition,boolQueryBuilder,depth+1);
        }
        queryBuilder.should(boolQueryBuilder);
      }
      return;
    }
    registry.getHandler(queryCondition.getOperator().getOperator()).
        buildQuerySyntaxForElasticSearch(queryBuilder, queryCondition);
  }
}
   각 조회 조건은builder 모드로 실현된다
public class ConditionBuilder {
  private List conditions;
  public ConditionBuilder() {
    conditions = new ArrayList<>();
  }
  public ConditionBuilder buildName(String name) {
    if (name != null) {
      conditions.add(buildCondition("name",name, FieldOperator.EQ));
    }
    return this;
  }
  
  public ConditionBuilder builderUserIds(List userIds) {
    if (CollectionUtils.isNotEmpty(userIds)) {
      conditions.add(buildCondition("userId", userIds, FieldOperator.IN));
    }
    return this;
  }
  
  // 
  public ConditionBuilder builderAge(Integer equalAge,Integer largeAge) {
    HybridCondition hybridCondition = new HybridCondition(Connector.AND);
    if (equalAge!=null) {
      HybridCondition temp = new HybridCondition(Connector.OR);
      temp.addCondition(buildCondition("age", equalAge, FieldOperator.EQ));
      hybridCondition.addCondition(temp);
    }
    if (largeAge!=null) {
      HybridCondition temp = new HybridCondition(Connector.OR);
      temp.addCondition(buildCondition("age", equalAge, FieldOperator.GE));
      hybridCondition.addCondition(temp);
    }
      if (!hybridCondition.getSubConditions().isEmpty()) {
      this.fieldObjects.add(hybridCondition);
    }
    return this;
  }
  
  public List getConditions() {
    return conditions;
  }
  private Condition buildCondition(String fieldName, Object value, FieldOperator operator) {
    Condition condition = new Condition();
    condition.setFieldName(fieldName);
    condition.setFieldValue(value);
    condition.setOperator(operator);
    return condition;
  }
}
   
                이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
spring-data-elasticsearch 페이지 조회부록: 1. 이름에서 알 수 있듯이QueryBuilder는 검색 조건, 필터 조건을 구축하는 데 사용되고 SortBuilder는 정렬을 구축하는 데 사용된다. 예를 들어 우리는 어느 위치에서 100미터 범위 내의 모...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.