由于某些需求,我们在查询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 } } } }
现在的返回结果,就是我们想要的列啦,只有一列,这里就完成了通过列来过滤查询值了。