代码之家  ›  专栏  ›  技术社区  ›  wscourge Kiran Balakrishnan

在一次扫描中将两个过滤器列表与MUST\u PASS\u ONE/ALL运算符合并

  •  2
  • wscourge Kiran Balakrishnan  · 技术社区  · 7 年前

    考虑hbase外壳 scan 'table' 结果:

    ROW COLUMN+CELL
    000 column=F:Q, timestamp=1519299345645, value=a
    001 column=F:Q, timestamp=1519299345645, value=b
    010 column=F:Q, timestamp=1519299345645, value=c
    011 column=F:Q, timestamp=1519299345645, value=b
    100 column=F:Q, timestamp=1519299345645, value=a
    110 column=F:Q, timestamp=1519299345645, value=c
    200 column=F:Q, timestamp=1519299345645, value=b
    210 column=F:Q, timestamp=1519299345645, value=a
    

    我想要什么作为我的 scan 结果:

    • 行键以开头 0 1
    • F:Q 值为 a b

    对于上述示例,其为:

    ROW COLUMN+CELL
    000 column=F:Q, timestamp=1519299345645, value=a
    001 column=F:Q, timestamp=1519299345645, value=b
    011 column=F:Q, timestamp=1519299345645, value=b
    100 column=F:Q, timestamp=1519299345645, value=a
    

    在hbase shell中( 全部忽略 \s \n 为了更好的可读性 ):

    import org.apache.hadoop.hbase.filter.CompareFilter
    import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
    import org.apache.hadoop.hbase.util.Bytes
    
    scan 'table' { 
      COLUMNS => 'F:Q', 
      FILTER => "
        (
          (PrefixFilter('0')) 
          OR 
          (PrefixFilter('1'))
        ) 
        AND 
        (
          SingleColumnValuFilter(
             Bytes.toBytes("F"),
             Bytes.toBytes("Q"),
             CompareFilter::CompareOp.valueOf('EQUAL'),
             Bytes.toBytes("a")
          )
          OR 
          SingleColumnValuFilter(
             Bytes.toBytes("F"),
             Bytes.toBytes("Q"),
             CompareFilter::CompareOp.valueOf('EQUAL'),
             Bytes.toBytes("b")
          )
        )
      "
    }
    

    因此,考虑一下java中有两个过滤器列表:

    List<Filter> prefixFilters            = new ArrayList<>();
    List<Filter> singleColumnValueFilters = new ArrayList();
    
    PrefixFilter one  = new PrefixFilter(Bytes.toBytes("1"));
    PrefixFilter zero = new PrefixFilter(Bytes.toBytes("0"));
    
    SingleColumnValueFilter a = new SingleColumnValueFilter(
        Bytes.toBytes("F"),
        Bytes.toBytes("Q"),
        CompareFilter.CompareOp.EQUAL,
        Bytes.toBytes("a") 
    );
    
    SingleColumnValueFilter b = new SingleColumnValueFilter(
        Bytes.toBytes("F"),
        Bytes.toBytes("Q"),
        CompareFilter.CompareOp.EQUAL,
        Bytes.toBytes("b") 
    );
    
    prefixFilters.add(zero);
    prefixFilters.add(one);
    
    singleColumnValueFilters.add(a);
    singleColumnValueFilters.add(b);
    
    FilterList prefixFiltersList = new FitlerList(FilterList.Operator.MUST_PASS_ONE, prefixFilters);
    FilterList singleColumnValueFiltersList = new FitlerList(FilterList.Operator.MUST_PASS_ONE, singleColumnValueFilters);
    

    问题: 如何将它们组合为一个 scan.setFilter() 使用 AND 接线员,就像我在炮弹里做的那样?


    我希望有特别的 FilterList 构造函数,它将接受逻辑比较器( 以及 / OR )和多个 List<Filter> 论据。既然没有,我就卡住了。
    1 回复  |  直到 7 年前
        1
  •  2
  •   Ben Watson    7 年前

    在末尾,添加

    FilterList filters = new FilterList(FilterList.Operator.MUST_PASS_ALL);
    filters.addFilter(prefixFiltersList);
    filters.addFilter(singleColumnValueFiltersList);
    
    scan.setFilter(filters);
    

    这可以确保两个过滤器列表都已运行,并且 MUST_PASS_ALL 充当 AND 条件

    为什么会这样?根据 FilterList JavaDoc :

    由于可以将过滤器列表用作过滤器列表的子级,因此可以创建要计算的过滤器层次结构。