반복 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에 따라 라이센스가 부여됩니다.