hbase2.1.x java SingleColumnValueFilter 过滤(有缺陷,列不存在时,也会查询出来)

上接:hbase2.1.x java 创建工程

说明

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:无操作,一般不用
  • 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'

步骤

  1. 获取table对象
  2. 构建过滤list
  3. 执行scan
  4. 迭代
  5. 关闭 ResultScanner
  6. 关闭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 列

解决

详见 链接


原文出处:/show_1IX1x6mGCLUf.html