关于HBase的SingleColumnValueFilter的坑

来源:互联网 发布:手机淘宝怎么换主题 编辑:程序博客网 时间:2024/06/05 15:24

由于某些需求,我们在查询hbase的时候,经常需要用到Filter。使用filter过滤来得到我们想要得到的值。
使用场景:我们需要通过Hbase里面的某些列的组合来查找符合这些条件的行。类似于mysql里面的where条件查询。根据列来查询。
下面是通过三列中的三个数据来查询到符合这三列的所有数据。
一般情况下,我们通过列来查询值,可能需要多个列组合的过滤。思路就是先创建一个FilterList,将需要的filter添加到filterList中。然后创建一个scan。

代码如下:

public class getValue{    public static void main(String args){       //将我们的查询条件放入到一个list里面       List<String> arr = new ArrayList<String>;       arr.add("列族,列1,value");       arr.add("列族,列2,value");       arr.add("列族,列3,value");       getValue.getFilterValue("表名",arr);     }   public static void getFilterValue(String tableName,List<String> arr){      //conf -> Configuration      HTable table = new HTable(conf,tableName);     List<Filter> filterList = new ArrayList<Filter>();//创建一个list来存放多个filter,默认下这些组合是“与”,”或“的话需注明     //创建一个Scan     Scan sc = new Scan();     for(String s:arr){          String[] arrS = s.split(",");          filterList.add(new SingleColumnValueFilter(Bytes.toBytes(arrS[0]),Bytes.toBytes(arrS[1]),CompareOp.EQUAL,new SubstringComparator(arrS[2])));              }     //添加过滤,只返回想要列     sc.addColumn(Bytes.toBytes("列族"),Bytes.toBytes("想要返回的列名"));     //将list添加到FilterList中     FilterList fl = new FiterList(filterList);     sc.setFilter(fl);     //定义一个ResultScanner来接收返回的值     ResultScanner ResultFilterValue = table.getScanner(sc);     for(Result r : ResultFilterValue ){        for(KeyValue kv : r.list()){        System.out.println(new String(kv.getRow)+"---->Row");        System.out.println(new String(kv.getValue)+"---->Value");        //....可以得到多个项,可查看API} }}}

很多人以为这就完了,但是运行结果看傻了(尴尬,尴尬我也是这样),因为从返回结果来看,返回了所有的值,但是返回的列只有我们需要的一个。这样看起来,代码没啥问题,但是filterList里面的filter好像没有起作用。
这是为啥呢。可能scan里面没有找到你需要的列吧,需要我们追加进去。
通过各种关键字google终于找到了一个方法。就是在添加filter的时候还要再将过滤的列添加到scan里面。

代码:

public class getValue{    public static void main(String args){       //将我们的查询条件放入到一个list里面       List<String> arr = new ArrayList<String>;       arr.add("列族,列1,value");       arr.add("列族,列2,value");       arr.add("列族,列3,value");       getValue.getFilterValue("表名",arr);     }   public static void getFilterValue(String tableName,List<String> arr){      //conf -> Configuration      HTable table = new HTable(conf,tableName);     List<Filter> filterList = new ArrayList<Filter>();//创建一个list来存放多个filter,默认下这些组合是“与”,”或“的话需注明     //创建一个Scan     Scan sc = new Scan();     for(String s:arr){          String[] arrS = s.split(",");          filterList.add(new SingleColumnValueFilter(Bytes.toBytes(arrS[0]),Bytes.toBytes(arrS[1]),CompareOp.EQUAL,new SubstringComparator(arrS[2])));          //在这里循环添加需要添加的列          sc.addColumn(Bytes.toBytes(s[0]),Bytes.toBytes(s[1]));              }     //添加过滤,只返回想要列     sc.addColumn(Bytes.toBytes("列族"),Bytes.toBytes("想要返回的列名"));     //将list添加到FilterList中     FilterList fl = new FiterList(filterList);     sc.setFilter(fl);     //定义一个ResultScanner来接收返回的值     ResultScanner ResultFilterValue = table.getScanner(sc);     for(Result r : ResultFilterValue ){        for(KeyValue kv : r.list()){        System.out.println(new String(kv.getRow)+"---->Row");        System.out.println(new String(kv.getValue)+"---->Value");        //....可以得到多个项,可查看API} }}}

在这里。终于可以长舒一口气了,但是现实总是残酷的,添加了这几句后,从返回结果来看,返回了只有我们想要的值,就是filterList里面的filter有效果了。但是又出现了一个新的问题,那就是返回的列就包括了多个,不止我们想要返回的列,还包含了我们添加的过滤的列。sc.addColumn(Bytes.toBytes(s[0]),Bytes.toBytes(s[1]));这里添加的列出现在了返回结果里面,但是通常来说我们只需要一个列的值,保存在一个对象里面,但是这样个返回值,存在多个列,不可能写个判断,先判断他是那一列,再取出我们想要的列吧。这。。。这就尴尬了。大哭
但是皇天不负有心人啊,通过查看hbase的API以及google,找到了解决办法 -->SingleColumnValueExcludeFilter。
代码:

public class getValue{    public static void main(String args){       //将我们的查询条件放入到一个list里面       List<String> arr = new ArrayList<String>;       arr.add("列族,列1,value");       arr.add("列族,列2,value");       arr.add("列族,列3,value");       getValue.getFilterValue("表名",arr);     }   public static void getFilterValue(String tableName,List<String> arr){      //conf -> Configuration      HTable table = new HTable(conf,tableName);     List<Filter> filterList = new ArrayList<Filter>();//创建一个list来存放多个filter,默认下这些组合是“与”,”或“的话需注明     //创建一个Scan     Scan sc = new Scan();     for(String s:arr){          String[] arrS = s.split(",");          filterList.add(new SingleColumnValueExcludeFilter(Bytes.toBytes(arrS[0]),Bytes.toBytes(arrS[1]),CompareOp.EQUAL,new SubstringComparator(arrS[2])));          //在这里循环添加需要添加的列          sc.addColumn(Bytes.toBytes(s[0]),Bytes.toBytes(s[1]));              }     //添加过滤,只返回想要列     sc.addColumn(Bytes.toBytes("列族"),Bytes.toBytes("想要返回的列名"));     //将list添加到FilterList中     FilterList fl = new FiterList(filterList);     sc.setFilter(fl);     //定义一个ResultScanner来接收返回的值     ResultScanner ResultFilterValue = table.getScanner(sc);     for(Result r : ResultFilterValue ){        for(KeyValue kv : r.list()){        System.out.println(new String(kv.getRow)+"---->Row");        System.out.println(new String(kv.getValue)+"---->Value");        //....可以得到多个项,可查看API} }}}


现在的返回结果,就是我们想要的列啦,只有一列,这里就完成了通过列来过滤查询值了。

1 0
原创粉丝点击