如何在HBase中对一行应用多个QualifierFilter?

7
我们希望使用两个QualifierFilters来过滤HBase表的扫描。这意味着我们只想获取表中具有特定列“col_A” (!)特定其他列“col_B”的行。
我们目前的方法如下:
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
Filter filter1 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator("col_A".getBytes()));
filterList.addFilter(filter1);
Filter filter2 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator("col_B".getBytes()));
filterList.addFilter(filter2);

Scan scan = new Scan();
scan.setFilter(filterList);
... 
未返回此扫描中的任何结果,尽管HBase表中有几行都具有'col_A'和'col_B'列。 <若仅对扫描应用filter1,则一切正常,我们确实可以获取所有具有'col_A'的行。 如果仅对扫描应用filter2,则情况也是如此。我们可以获得所有具有'col_B'的行。

<仅当我们结合这两个过滤器时,才不会获得任何结果。

<获取仅具有col_A AND col_B的表行的正确方法是什么?

2个回答

3
您可以通过定义以下过滤器来实现此目的:
List<Filter> filters = new ArrayList<Filter>(2);
byte[] colfam = Bytes.toBytes("c");
byte[] fakeValue = Bytes.toBytes("DOESNOTEXIST");
byte[] colA = Bytes.toBytes("col_A");
byte[] colB = Bytes.toBytes("col_B");

SingleColumnValueFilter filter1 = 
    new SingleColumnValueFilter(colfam, colA , CompareOp.NOT_EQUAL, fakeValue);  
filter1.setFilterIfMissing(true);
filters.add(filter1);

SingleColumnValueFilter filter2 = 
    new SingleColumnValueFilter(colfam, colB, CompareOp.NOT_EQUAL, fakeValue);          
filter2.setFilterIfMissing(true);
filters.add(filter2);

FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, filters);
Scan scan = new Scan();
scan.setFilter(filterList);

这里的想法是为每个要查找的列定义一个SingleColumnValueFilter,每个过滤器都有一个虚假值和一个CompareOp.NOT_EQUAL运算符。也就是说,这样的SingleColumnValueFilter将返回给定名称的所有列。
来源:http://mapredit.blogspot.com/2012/05/using-filters-in-hbase-to-match-two.html

谢谢您的回答。我刚试了一下,它适用于我们的情况。但问题是关于性能的。我假设过滤器按照它们放入FilterList的顺序进行评估。因此,如果我有许多行存在col_A,则HBase必须针对该列中的实际值进行检查。这听起来非常昂贵。是否有任何方法可以在检查实际单元格值之前先评估两个列的存在? - Henrik
@Henrik,我不知道你有多少数据,但恐怕你是对的。另一个选择是实现一个自定义过滤器,它可以获取你要查找的限定符列表。 - Lorand Bendig
QualifierFilter可以过滤掉不需要的列,但是你的解决方案却没有。 - Kerim Karaca

3
我认为这行代码有问题 -
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);

你希望它是什么 -
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE);

过滤器将尝试查找既具有列修饰符又不存在该列的列。

欢迎来到StackOverflow!当问题尚未得到提问者满意的解答或者你有其他解决方案时,你的回答将会受到最高赞赏。此外,在撰写答案时,请点击help链接以了解如何格式化回答以实现最佳可读性。 - dg99

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接