摸索了几天Hbase关于利用Filter去做scan,也是很有体会。
先简单介绍一下我的表结构,然后描述我的需求,最后给出利用Filter去查询的方案。
rowkey:Filename+index1+index2 例子:xxx_4_9 (其中xxx为filename,4为index1,9为index2),列簇设计为:Info和Data两组,其中Info就包含一些常规信息,Data中的列是按照ID构造,即1,2,3......,即为:Data:1,Data:2...
1、根据rowkey前缀查询数据
根据filename和index1进行查询,其中index1是一个区间,函数接口如下:
getFileData(String Filename, int from, int to)
通常Filter可以传入两个参数,第一个参数是比较运算符CompareOp,第二个参数是比较器ByteArrayComparable。
其中比较运算符有如下:
EQUAL 相等
GREATER 大于
GREATER_OR_EQUAL 大于等于
LESS 小于
LESS_OR_EQUAL 小于等于
NOT_EQUAL 不等于
比较器有如下:
BinaryComparator 匹配完整字节数组
BinaryPrefixComparator 匹配字节数组前缀
BitComparator Performs a bitwise comparison, providing a BitwiseOp class with OR, and XOR operators.
NullComparator Does not compare against an actual value but whether a given one is null, or not null.
RegexStringComparator 正则表达式匹配
SubstringComparator 子串匹配
关于这里的任务,可以用PrefixFilter去做,但是这个PrefixFilter不能传入比较运算符和比较器,只能传入前缀字符串。
当然可以用FilterList,其中FilterList可以设置 MUST_PASS_ONE或MUST_PASS_ALL条件,这里也尝试了利用FilterList,结合其他的RowFilter去做,如果利用BinaryPrefixComparator,会出现的问题就是说,想匹配xxx_4_all,那么有可能会匹配出xxx_40_,xxx_41_....,如果用RegexStringComparator去匹配,只能用EQUAL,而不能用GREATER_OR_EQUAL等条件,这里给出一种方案是,利用PrefixFilter,结合FillterList,将from和to生成一个list,然后对每个list设置一个PrefixFilter,然后加入到FilterList中,具体代码如下:
Scan scan = new Scan();
int FROM = from;
ArrayList range = new ArrayList<>();
while (FROM <= to) {
range.add(String.valueOf(FROM));
FROM++;
}
FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE);
for (String s : range) {
PrefixFilter filter = new PrefixFilter(Bytes.toBytes(Filename + "_" + s + "_"));
list.addFilter(filter);
}
scan.setFilter(list);
//使用HTable得到resultcanner实现类的对象
ResultScanner resultScanner = table.getScanner(scan);
2、根据Rowkey并指定列名
具体要求就是在前一个任务的基础之上,不是过滤出所有的数据,而是指定相关列名,具体函数接口如下:
getFileData(String Filename, int from, int to, String... columns)
给出方案如下:
一个FilterList用于过滤Rowkey,一个FilterList用于过滤列名,这两个FilterList,均采用MUST_PASS_ONE条件,然后将这两个FilterList,加入一个总的FilterList中,条件采用MUST_PASS_ALL,具体代码如下:
//得到用于扫描region的对象
Scan scan = new Scan();
int FROM = from;
ArrayList range = new ArrayList<>();
while (FROM <= to) {
range.add(String.valueOf(FROM));
FROM++;
}
FilterList list_all = new FilterList(FilterList.Operator.MUST_PASS_ALL);
FilterList list_col = new FilterList(FilterList.Operator.MUST_PASS_ONE);
for (String column : columns) {
Filter filter_col = new QualifierFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(column)));
list_col.addFilter(filter_col);
}
FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE);
for (String s : range) {
PrefixFilter filter = new PrefixFilter(Bytes.toBytes(Filename + "_" + s + "_"));
list.addFilter(filter);
}
list_all.addFilter(list_col);
list_all.addFilter(list);
scan.setFilter(list_all);
//使用HTable得到resultcanner实现类的对象
ResultScanner resultScanner = table.getScanner(scan);
总结起来,如果要利用scan和filter结合进行数据查询,那么需要去了解有哪些Filter,然后构造自己的Filter,这里给出一个Filter写的比较全的博客:Filter