登录    关于
马育民老师的博客

马育民的博客

QQ:65242847

hbase2.1.x java SingleColumnValueFilter 列不存在时,无法过滤,满足所有过滤条件

描述问题

添加测试数据

put 'student2','1000','info:name','lilei'
put 'student2','1000','info:age','20'

put 'student2','1001','info:name','lucy'
put 'student2','1001','info:age','19'

put 'student2','1002','info:name','hanmeimei'
put 'student2','1002','info:age','23'

put 'student2','1003','info:name','lili'

注意: rowkey1003 的,只有 name,没有 age

代码

package hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

public class Std7_条件查询 {

    private static final Logger LOG= Logger.getLogger(Std7_条件查询.class);
    private Connection conn;
    /**
     * 创建hbase连接
     * @throws IOException
     */
    public void conn() throws IOException {
        //创建hbase配置对象
        Configuration conf= HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "hadoop1,hadoop2,hadoop3");// zookeeper地址
        conf.set("hbase.zookeeper.property.clientPort", "2181");// zookeeper端口
        //通过配置对象创建连接
        conn = ConnectionFactory.createConnection(conf);
    }
    /**
     * 关闭连接
     * @throws IOException
     */
    public void close() throws IOException {
        conn.close();
    }

public void query() throws IOException {
    TableName tn = TableName.valueOf("student2");
    Table table = conn.getTable(tn);
    //大于等于20
    SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
            Bytes.toBytes("info")
            , Bytes.toBytes("age")
            , CompareOperator.GREATER_OR_EQUAL
            , new BinaryComparator(Bytes.toBytes("20")));

    //小于等于22
    SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
            Bytes.toBytes("info")
            , Bytes.toBytes("age")
            , CompareOperator.LESS_OR_EQUAL
            , new BinaryComparator(Bytes.toBytes("22")));

    //当 某条记录不含age 列是,查询条件是否生效,true表示生效,即:不包含该条记录
//    filter1.setFilterIfMissing(true);
//    filter2.setFilterIfMissing(true);

    //构建这2个filter的关系 ,相当于 and
    FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, filter1, filter2);

    Scan scan = new Scan();
    //将 filterlist传入 scan
    scan.setFilter(filterList);

    ResultScanner scanner = table.getScanner(scan);
    Iterator<Result> iterator = scanner.iterator();


    while(iterator.hasNext()){
        System.out.println("--------------------------");

        Result result = iterator.next();


        //获取rowkey
        String rowkey=Bytes.toString(result.getRow());

        System.out.println("rowKey:"+rowkey);

        List<Cell> cells = result.listCells();
        for(Cell item : cells){
            String family=Bytes.toString(item.getFamilyArray(),item.getFamilyOffset(),item.getFamilyLength());
            String qualifier=Bytes.toString(item.getQualifierArray(),item.getQualifierOffset(),item.getQualifierLength());
            String value=Bytes.toString(item.getValueArray(),item.getValueOffset(),item.getValueLength());

            System.out.println(family+":"+qualifier+",value="+value);
        }


    }
    scanner.close();
    table.close();

}

    public static void main(String[] args) throws IOException {
        Std7_条件查询 hbase=new Std7_条件查询();
        hbase.conn();
        System.out.println("connect ok!");

        hbase.query();


        hbase.close();
        System.out.println("close ok!");
    }
}

查询结果:

--------------------------
rowKey:1000
info:age,value=20
info:name,value=lilei
--------------------------
rowKey:1003
info:name,value=lili

因为 lili 没有 age ,在 hbase 中,默认 满足所有过滤条件

解决

关键代码

当 某条记录不含过滤条件的列,查询条件仍然生效(true表示生效),即:不包含该条记录

filter1.setFilterIfMissing(true);
filter2.setFilterIfMissing(true);

完整代码

package hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

public class Std7_条件查询 {

    private static final Logger LOG= Logger.getLogger(Std7_条件查询.class);
    private Connection conn;
    /**
     * 创建hbase连接
     * @throws IOException
     */
    public void conn() throws IOException {
        //创建hbase配置对象
        Configuration conf= HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", "hadoop1,hadoop2,hadoop3");// zookeeper地址
        conf.set("hbase.zookeeper.property.clientPort", "2181");// zookeeper端口
        //通过配置对象创建连接
        conn = ConnectionFactory.createConnection(conf);
    }
    /**
     * 关闭连接
     * @throws IOException
     */
    public void close() throws IOException {
        conn.close();
    }

public void query() throws IOException {
    TableName tn = TableName.valueOf("student");
    Table table = conn.getTable(tn);
    //大于等于20
    SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
            Bytes.toBytes("info")
            , Bytes.toBytes("age")
            , CompareOperator.GREATER_OR_EQUAL
            , new BinaryComparator(Bytes.toBytes("20")));

    //小于等于22
    SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
            Bytes.toBytes("info")
            , Bytes.toBytes("age")
            , CompareOperator.LESS_OR_EQUAL
            , new BinaryComparator(Bytes.toBytes("25")));

    //当 某条记录不含age 列是,查询条件是否生效,true表示生效,即:不包含该条记录
    filter1.setFilterIfMissing(true);
    filter2.setFilterIfMissing(true);

    //构建这2个filter的关系 ,相当于 and
    FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, filter1, filter2);

    Scan scan = new Scan();
    //将 filterlist传入 scan
    scan.setFilter(filterList);

    ResultScanner scanner = table.getScanner(scan);
    Iterator<Result> iterator = scanner.iterator();


    while(iterator.hasNext()){
        System.out.println("--------------------------");

        Result result = iterator.next();


        //获取rowkey
        String rowkey=Bytes.toString(result.getRow());

        System.out.println("rowKey:"+rowkey);

        List<Cell> cells = result.listCells();
        for(Cell item : cells){
            String family=Bytes.toString(item.getFamilyArray(),item.getFamilyOffset(),item.getFamilyLength());
            String qualifier=Bytes.toString(item.getQualifierArray(),item.getQualifierOffset(),item.getQualifierLength());
            String value=Bytes.toString(item.getValueArray(),item.getValueOffset(),item.getValueLength());

            System.out.println(family+":"+qualifier+",value="+value);
        }


    }
    scanner.close();
    table.close();

}

    public static void main(String[] args) throws IOException {
        Std7_条件查询 hbase=new Std7_条件查询();
        hbase.conn();
        System.out.println("connect ok!");

        hbase.query();


        hbase.close();
        System.out.println("close ok!");
    }
}

查询结果:

--------------------------
rowKey:1000
info:age,value=20
info:name,value=lilei

正确


原文出处:http://malaoshi.top/show_1IX2JiGBMM4G.html