说明
SingleColumnValueFilter 过滤器功能强大,相当于 SQL where 部分,支持多个条件
过滤器 构造方法
参见:https://hbase.apache.org/2.1/devapidocs/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.html
SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOperator op, byte[] value)
解释:
family:列族qualifier:列op:比较运算符,有如下值:- LESS:小于,相当于
< - LESS_OR_EQUAL::小于等于,相当于
<= - EQUAL:等于,相当于
= - NOT_EQUAL:不等于,相当于
!= - GREATER_OR_EQUAL:大于等于,相当于
>= - GREATER:大于,相当于
> - NO_OP:无操作,一般不用
- LESS:小于,相当于
value:表达式
注意
- 列名大小写一定要正确,写错不报错,但会查询不到数据
例子:查询姓名是李雷
相当于 select * from student where name='李雷'
SingleColumnValueFilter filter=new SingleColumnValueFilter(
Bytes.toBytes("c1"), //列族名
Bytes.toBytes("name"), //列名
CompareOperator.EQUAL, // 比较运算符
new BinaryComparator(Bytes.toBytes("李雷"))); // 值
例子:查询年龄大于20
相当于 select * from student where age>'20'
SingleColumnValueFilter filter=new SingleColumnValueFilter(
Bytes.toBytes("c1"), //列族名
Bytes.toBytes("age"), //列名
CompareOperator.GREATER, // 比较运算符
new BinaryComparator(Bytes.toBytes("20"))); // 值
例子:查询身高小于等于 1.85
相当于 select * from student where length<='1.85'
SingleColumnValueFilter filter=new SingleColumnValueFilter(
Bytes.toBytes("c1"), //列族名
Bytes.toBytes("length"), //列名
CompareOperator.LESS_OR_EQUAL, // 比较运算符
new BinaryComparator(Bytes.toBytes("1.85"))); // 值
添加测试数据
清空表:
truncate 'book'
添加数据:
put 'book','1001','c1:title','htlm从入门到放弃'
put 'book','1001','c1:author','lucy'
put 'book','1001','c1:price','097.50'
put 'book','1002','c1:title','css从入门到放弃'
put 'book','1002','c1:author','lili'
put 'book','1002','c1:price','099.90'
put 'book','1003','c1:title','hadoop从入门到放弃'
put 'book','1003','c1:author','韩梅梅'
put 'book','1003','c1:price','190.00'
put 'book','1003','c1:title','hbase从入门到精通'
put 'book','1003','c1:author','李雷'
put 'book','1003','c1:price','029.50'
步骤
- 获取table对象
- 构建过滤list
- 执行scan
- 迭代
- 关闭
ResultScanner - 关闭table
单条件查询
完整代码
// 传入 =,>,>=,<,<=,!=,返回相对应的 CompareOperator
CompareOperator getCompareOperator(String op){
CompareOperator co = null;
switch (op) {
case "=":
co = CompareOperator.EQUAL;
break;
case ">":
co = CompareOperator.GREATER;
break;
case ">=":
co = CompareOperator.GREATER_OR_EQUAL;
break;
case "<":
co = CompareOperator.LESS;
break;
case "<=":
co = CompareOperator.LESS_OR_EQUAL;
break;
case "!=":
co = CompareOperator.NOT_EQUAL;
break;
default:
co = CompareOperator.NO_OP;
}
return co;
}
/**
*
* @param tableName 表名
* @param columnFamily 列族名
* @param column 列名
* @param op 操作,=,>,>=,<,<=,!=
* @param value 值
* @throws IOException
*/
public List<CellData[]> filter(String tableName, String columnFamily, String column, String op, String value) throws IOException {
Table table = conn.getTable(TableName.valueOf(tableName));
//创建Scan
Scan scan=new Scan();
SingleColumnValueFilter filter=new SingleColumnValueFilter(
Bytes.toBytes(columnFamily),
Bytes.toBytes(column),
getCompareOperator(op),
new BinaryComparator(Bytes.toBytes(value))); // 注意是字符串
//传入filter
scan.setFilter(filter);
//执行scan
ResultScanner resultScanner = table.getScanner(scan);
Iterator<Result> iterator = resultScanner.iterator();
List<CellData[]> retList = new ArrayList<>();
//迭代,在迭代时,ResultScanner会发送get请求
while(iterator.hasNext()){
Result result=iterator.next();
//获取rowkey
String rowkey=Bytes.toString(result.getRow());
// System.out.print(rowkey+"\t");
//获取所有单元格
List<Cell> list=result.listCells();
CellData[] arr = new CellData[list.size()];
int i = 0;
for(Cell item:list){
String family=Bytes.toString(CellUtil.cloneFamily(item));
String qualifier=Bytes.toString(CellUtil.cloneQualifier(item));
String valueDb=Bytes.toString(CellUtil.cloneValue(item));
CellData cellData = new CellData(family,qualifier,rowkey,item.getTimestamp(),valueDb);
arr[i] = cellData ;
i ++ ;
}
retList.add(arr);
}
//用完要及时关闭,在迭代时,ResultScanner会发送get请求
resultScanner.close();
table.close();
return retList;
}
测试
查询 price 是 099.90的数据
public static void main(String[] args) throws IOException {
HbaseUtils2_filter utils=new HbaseUtils2_filter();
utils.connect();
// 查询 price 小于等于 099.90的数据
List<CellData[]> resList = utils.filter("book", "c1", "price", "<=", "099.90");
for(CellData[] arr : resList){
for(CellData item : arr){
// System.out.println(item.getFamily()+":"+item.getQualifier()+"-"+item.getTimestamp()+" == "+item.getValue());
System.out.print(item.getFamily()+":"+item.getRowkey()+":"+item.getQualifier() +" == "+item.getValue()+"\t\t");
}
System.out.println("----------");
}
utils.close();
}
缺陷
当数据没有 price 列时,也是满足条件的,也能查询出来
验证
添加数据:
put 'book','1015','c1:title','水浒传'
再次执行查询,发现能够查询出该条记录,虽然该记录没有 price 列
解决
详见 链接