Hbase过滤器
一·:hbase 过滤器的比较运算符: CompareOp
- LESS <
- LESS_OR_EQUAL <=
- EQUAL =
- NOT_EQUAL <>
- GREATER_OR_EQUAL >=
- GREATER >
- NO_OP 排除所有
二:HBase 过滤器的比较器(指定比较机制):
- BinaryComparator 按字节索引顺序比较指定字节数组,采用 Bytes.compareTo(byte[])
- BinaryPrefixComparator 跟前面相同,只是比较左端的数据是否相同
- NullComparator 判断给定的是否为空
- BitComparator 按位比较
- RegexStringComparator 提供一个正则的比较器,仅支持 EQUAL 和非 EQUAL
- SubstringComparator 判断提供的子串是否出现在 value 中。
三:过滤器的分类
1.指定扫描
public static void scanTable(String tableNanme,String rowkeyStart,String rowkeyStop,
String family,String qualifier,long minStamp,long maxStamp,String qualifier2,String age) throws IOException {
//1.获取表对象
Table table=connection.getTable(TableName.valueOf(tableNanme));
//2.创建一个scan对象
Scan scan=new Scan();
//2.1指定列族
//scan.addFamily(family.getBytes());
//2.2指定列
//scan.addColumn(Bytes.toBytes(family), qualifier.getBytes());
//2.3指定时间戳范围
//2.3.1指定单个时间戳
//scan.setTimeStamp(minStamp);
//2.3.2指定时间戳范围(含头不含尾)
//scan.setTimeRange(minStamp, maxStamp);
//3.指定行键范围,因为底层存储会按行键的范围进行排序,所以可以指定范围
//scan.setStartRow(rowkeyStart.getBytes());
//scan.setStopRow(rowkeyStop.getBytes());
//4.扫描全表
ResultScanner resultScanner=table.getScanner(scan);
//4.解析resultScanner
for (Result result : resultScanner) {//取出一个个的result
//5.解析result
for (Cell cell:result.rawCells()) {
//6.打印数据
System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+","+"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+"Value:"+Bytes.toString(CellUtil.cloneValue(cell)));
}
}
//7.关闭表连接
table.close();
}
2.比较过滤器:
-
FamilyFilter 针对列族过滤
/** * 构造列族比较器对象 * 参数1:比较运算符 * 参数2:比较器(比较规则) */ Filter f1= new FamilyFilter(CompareOp.EQUAL, new BinaryComparator("info01".getBytes()));
-
QulifierFilter 列名过滤器
/** * 构造列名比较器对象 * 参数1:比较运算符 * 参数2:比较器(比较规则) */ Filter f2=new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(qualifier2.getBytes())); final ByteArrayComparable qualifierComparator)
-
ValueFilter 列值过滤器
/** * 构造列值比较器对象 * 参数1:比较运算符 * 参数2:比较器(比较规则) */ Filter f3=new ValueFilter(CompareOp.LESS_OR_EQUAL,new BinaryComparator(Bytes.toBytes(age)));
-
RowFilter 行健过滤器
/** * 构造行键比较器对象 * 参数1:比较运算符 * 参数2:比较器(比较规则) */ Filter filter1 = new RowFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("user0000")));
-
TimestampsFilter 时间戳过滤器
时间戳比较器一般要使用到集合,可以添加一个集合为TimestampsFilter参数
List<Long> ts = new ArrayList<Long>(); tss.add(1495398833002l); Filter filter1 = new TimestampsFilter(ts); scan.setFilter(filter1);
-
过滤器连用
MUST_PASS_ALL:过滤器都通过
MUST_PASS_ONE:过滤器只使用一个/** * 多个过滤器连用 * 参数1:指定多个过滤器的逻辑计算关系 * 参数2:指定连用的过滤器 */ FilterList f4=new FilterList(Operator.MUST_PASS_ALL, f2,f3);
一般的比较过滤器的构造方法的参数
参数1:
CompareOp valueCompareOp 指定比较操作符
> >= < <= == !=
public enum CompareOp {
/** less than */
LESS,//小于
/** less than or equal to */
LESS_OR_EQUAL,//小于等于
/** equals */
EQUAL,//等于
/** not equal */
NOT_EQUAL,//不等于
/** greater than or equal to */
GREATER_OR_EQUAL,//大于等于
/** greater than */
GREATER,//大于
/** no operation */
NO_OP,//不比较
}
参数2
指定比较值
BinaryComparator 按照字节进行比较
BinaryPrefixComparator 跟前面相同,只是比较左端的数据是否相同
NullComparator 判断给定的是否为空
BitComparator 按位比较
RegexStringComparator 提供一个正则的比较器,仅支持 EQUAL 和非 EQUAL
SubstringComparator 判断提供的子串是否出现在 value 中。
2.专用过滤器
-
单列值过滤器 SingleColumnValueFilter ----会返回满足条件的整行
/** * 专用过滤器——值过滤器 */ public static void scan_sr(String tablename,String family,String qualifier,String value,String prefix) throws IOException { //获取表连接 Table table=connection.getTable(TableName.valueOf(tablename)); //创建扫描对象 Scan scan=new Scan(); //创建但值过滤器 SingleColumnValueFilter sr=new SingleColumnValueFilter(family.getBytes(), qualifier.getBytes(), CompareOp.EQUAL, Bytes.toBytes(value)); //sr.setFilterIfMissing(true); //设置扫描器 scan.setFilter(sr); //scan.addColumn(family.getBytes(), qualifier.getBytes()); //获取全局扫描的结果 ResultScanner scanner=table.getScanner(scan); //遍历获取 for (Result result : scanner) { for (Cell cell : result.rawCells()) { System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+"," +"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+ "Value:"+Bytes.toString(CellUtil.cloneValue(cell))); } } }
关于单值过滤器SingleColumnValueFilter的坑:如果仅仅只使用单值过滤器返回不是我们想要的结果,例如有如下数据:
ROW COLUMN+CELL 000001 column=info01:name, timestamp=1571814795977, value=pikce1_2 000001 column=info02:age, timestamp=1571915607101, value=11 000002 column=info01:age, timestamp=1571915577077, value=22 000002 column=info01:name, timestamp=1571814796770, value=pikce2_2 000002 column=info02:age, timestamp=1571915591755, value=10 000003 column=info01:age, timestamp=1571887612984, value=12 000003 column=info01:name, timestamp=1571815672698, value=pick02 000003 column=info02:age, timestamp=1571887633662, value=12 000004 column=info01:age, timestamp=1571916710317, value=22 000004 column=info02:age, timestamp=1571887661213, value=22 000004 column=info02:name, timestamp=1571889126588, value=20 000005 column=info01:age, timestamp=1571916718840, value=22 100005 column=info01:age, timestamp=1571918114145, value=22 100006 column=info01:age, timestamp=1571924100668, value=22
使用单值过滤器:
SingleColumnValueFilter sr=new SingleColumnValueFilter("info01".getBytes(), "age".getBytes(), CompareOp.EQUAL, Bytes.toBytes("22")); scan.setFilter(sr);
出来的结果如下,会发现离我们理想的结果偏差很大,多了一些我们并不想要的结果
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2 rowkey:000001,family:info02,qualifiler:age,Value:11 rowkey:000002,family:info01,qualifiler:age,Value:22 rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2 rowkey:000002,family:info02,qualifiler:age,Value:10 rowkey:000004,family:info01,qualifiler:age,Value:22 rowkey:000004,family:info02,qualifiler:age,Value:22 rowkey:000004,family:info02,qualifiler:name,Value:20 rowkey:000005,family:info01,qualifiler:age,Value:22 rowkey:100005,family:info01,qualifiler:age,Value:22 rowkey:100006,family:info01,qualifiler:age,Value:22
如何解决的:scan的时候还需要再加上过滤,如下
scan.addColumn(family.getBytes(), qualifier.getBytes());
加上过滤之后的结果:
rowkey:000002,family:info01,qualifiler:age,Value:22 rowkey:000004,family:info01,qualifiler:age,Value:22 rowkey:000005,family:info01,qualifiler:age,Value:22 rowkey:100005,family:info01,qualifiler:age,Value:22 rowkey:100006,family:info01,qualifiler:age,Value:22
-
单列值排除器 SingleColumnValueExcludeFilter -----返回排除了该列的结果
//创键单值排除器 SingleColumnValueExcludeFilter ser=new SingleColumnValueExcludeFilter(family.getBytes(), qualifier.getBytes(), CompareOp.EQUAL, Bytes.toBytes(value));
使用单列值排除器 SingleColumnValueExcludeFilter的坑:由于使用的排除器是返回的不满足给出的条件的数据,所以这时就不能再scan的时候添加过滤,再添加了就不会有结果返回来
-
行键前缀过滤器 PrefixFilter----针对行键
//创键单值排除器 PrefixFilter ser=new PrefixFilter(prefix.getBytes());
-
列前缀过滤器 ColumnPrefixFilter
//创建行键前缀过滤器 PrefixFilter pr=new PrefixFilter(Bytes.toBytes(prefix)); scan.setFilter(pr);
-
分页过滤器 PageFilter
public static void Scan_page(String tablename,String startRow,int pageSize) throws IOException {
Table table=connection.getTable(TableName.valueOf(tablename));
//创建扫描器对象
Scan scan=new Scan();
//创建分页过滤器,第一步设置起始位置,第二部设置每页的条数
//scan.setStartRow(startRow.getBytes());
PageFilter page=new PageFilter(pageSize);
//创建扫描器
scan.setFilter(page);
//获取扫描结果
ResultScanner scanner=table.getScanner(scan);
//遍历扫描结果
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+","+"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+"Value:"+Bytes.toString(CellUtil.cloneValue(cell)));
}
}
}
分页过滤器测试如下:
Scan_page("HbaseAPI:HbaseAPI01", "000001",1);
运行的结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
Scan_page("HbaseAPI:HbaseAPI01", "000001",2);
运行的结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
rowkey:000002,family:info01,qualifiler:age,Value:22
rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2
rowkey:000002,family:info02,qualifiler:age,Value:10
Scan_page("HbaseAPI:HbaseAPI01", "000001",3);
运行结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
rowkey:000002,family:info01,qualifiler:age,Value:22
rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2
rowkey:000002,family:info02,qualifiler:age,Value:10
rowkey:000003,family:info01,qualifiler:age,Value:12
rowkey:000003,family:info01,qualifiler:name,Value:pick02
rowkey:000003,family:info02,qualifiler:age,Value:12
综合上面的测试可以发现,PageFilter page=new PageFilter(pageSize),传入的参数page在分页的时候就是代表了行键的个数,并不是代表有几条数据,每一页显示的数据个数是由行键决定的,并且是行键由小到大排序的