设为首页 加入收藏

TOP

运用组合模式实现复合搜索条件构建(一)
2018-02-22 14:32:41 】 浏览:554
Tags:运用 组合 模式 实现 复合 搜索 条件 构建

在订单搜索中,有时需要实现复合搜索,比如 ( A must B ) or ( C must D ) 或者 (A or C) must ( B or D ) 。 这就需要能够灵活地组合条件,条件可以是原子的或复合的。可以使用组合模式来实现。

思路

要实现复合搜索条件的构建,需要解决两个问题:A. 如何表示复合搜索条件; B. 如何将复合搜索条件转换为合适的ES查询对象。对于A来说,关键就是搜索条件可灵活组合,用组合模式再合适不过;对于B来说,需要知道ES如何表示这些复合搜索。

(A must B ) or ( C must D) 的 ES 表示为:

{"query":{"bool":{"should":[{"bool":{"must":[{"term":{"shop_id":63077}},{"terms":{"state":[1,2,3,4,5]}}]}},{"bool":{"must":[{"term":{"shop_id":63077}},{"range":{"book_time":{"gt":1516550400}}},{"terms":{"order_tags":["IS_SECURED_TRANSACTIONS"]}}]}}],"minimum_should_match":1}},"from":0,"size":10}

( A or B ) must ( C or D ) 的 ES 表示是:

bool:{must:[{bool:{should:[{A},{C}],minimum_should_match: 1}},{bool:{should:[{D},{B}], minimum_should_match: 1}}]}

组合模式的要点是:原子条件和复合条件具备相同的行为接口,从而能够组合和叠加。

实现

组合模式

STEP1: 首先定义 Condition 接口, 目前仅支持 与 和 或 操作,以及查询对象转换。

/**
 * Created by shuqin on 18/2/7.
 */
public interface Condition {

  Condition and(Condition c);
  Condition or(Condition c, Integer shouldMinimumMatch);
  Map expr();    // ES 查询对象

  default String json() {
    return JSON.toJSONString(this);
  }

}

STEP2: 原子条件 EsCondition 实现

package zzz.study.patterns.composite.escondition;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import lombok.Data;

/**
 * Created by shuqin on 18/2/8.
 */
@Data
public class EsCondition implements Condition, Serializable {

  private static final long serialVersionUID = -209082552315760372L;

  /** ES 字段名称 */
  private String fieldName;

  /** 匹配符 */
  private Op op;

  /**
   *
   * 要匹配的值,用于 eq, neq, range, in, match
   *
   * eq 传 单个值对象,比如 Integer, String , etc
   * in 传 List 对象
   * range 传 Range 对象
   * match 传 Match 对象
   *
   */
  private Object value;

  public EsCondition() {
  }

  public EsCondition(String fieldName, Op op, Object value) {
    this.fieldName = fieldName;
    this.op = op;
    this.value = value;
  }

  public String getFieldName() {
    return fieldName;
  }

  public Op getOp() {
    return op;
  }

  public Object getValue() {
    return value;
  }

  @Override
  public String toString() {
    return "EsCondition{" +
           "fieldName='" + fieldName + '\'' +
           ", op=" + op +
           ", value=" + value +
           '}';
  }

  @Override
  public Condition and(Condition c) {
    return new CompositeMustCondition(Lists.newArrayList(c, this));
  }

  @Override
  public Condition or(Condition c, Integer shouldMinimumMatch) {
    List<Condition> shouldConditions = Lists.newArrayList(c, this);
    return new CompositeShouldCondition(shouldConditions, shouldMinimumMatch);
  }

  private static Map<String, String> op2EsKeyMap = ImmutableMap.of(
      Op.eq.name(), "term",
      Op.neq.name(), "term",
      Op.in.name(), "terms",
      Op.range.name(), "range",
      Op.match.name(), "match"
  );

  @Override
  public Map expr() {
    return buildEsExpr(op2EsKeyMap.get(op.name()));
  }

  private Map buildEsExpr(String esKey) {
    r
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇正确的打日志姿势 下一篇再谈 websocket 论架构设计

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目