hbase:使用动态创建的限定符查询特定值

时间:2012-07-23 06:35:52

标签: java hbase

HY,

Hbase允许列族在不同的行中具有不同的限定符。在我的情况下,列族具有以下规范

abc[cnt] # where cnt is an integer that can be any positive integer

我想要实现的是获取来自不同列族的所有数据,只有当所描述的限定符(在不同的列族中)的值匹配时才会获得。

缩小扫描范围我只需添加查询所需的两个系列。但这就是我现在所能得到的。

我已经使用SingleColumnValueFilter实现了相同的行为,但事后已知限定符。但对于这个,限定符可以是 abc1 abc2 ......会有太多的选项,因此有太多的SingleColumnValueFilter。

然后我尝试使用ValueFilter,但此过滤器仅返回与值匹配的列,因此返回错误的列族。

您能想到实现目标的任何方法,查询列族中动态创建的限定符中的值并返回列族和其他列族的内容(如创建扫描时指定的那样)?最好只查询一次。

提前感谢任何输入。

更新:(有关评论中所述的说明)

以更加图形化的方式,行可能具有以下内容:

colfam1:aaa
colfam1:aab
colfam1:aac
colfam2:abc1
colfam2:abc2

然而,如果 colfam2的任何值具有例如,那么我想得到所有家族colfam1值x,关于colfam2:abc [cnt]是动态创建的事实,cnt是任何正整数

1 个答案:

答案 0 :(得分:3)

我看到两种方法:客户端过滤或服务器端过滤。

客户端过滤更直接。扫描仅添加两个系列“colfam1”和“colfam2”。然后,对于从Result获得的每个scanner.next(),您必须根据“colfam2”中的限定符进行过滤。

byte[] queryValue = Bytes.toBytes("x");
Scan scan = new Scan();
scan.addFamily(Bytes.toBytes("colfam1");
scan.addFamily(Bytes.toBytes("colfam2");
ResultScanner scanner = myTable.getScanner(scan);
Result res;
while((res = scanner.next()) != null) {
   NavigableMap<byte[],byte[]> colfam2 = res.getFamilyMap(Bytes.toBytes("colfam2"));
   boolean foundQueryValue = false;
   SearchForQueryValue: while(!colfam2.isEmpty()) {
       Entry<byte[], byte[]> cell = colfam2.pollFirstEntry();
       if( Bytes.equals(cell.getValue(), queryValue) ) {
           foundQueryValue = true;
           break SearchForQueryValue;
       }
   }
   if(foundQueryValue) {
       NavigableMap<byte[],byte[]> colfam1 = res.getFamilyMap(Bytes.toBytes("colfam1"));
       LinkedList<KeyValue> listKV = new LinkedList<KeyValue>();
       while(!colfam1.isEmpty()) {
           Entry<byte[], byte[]> cell = colfam1.pollFirstEntry();
           listKV.add(new KeyValue(res.getRow(), Bytes.toBytes("colfam1"), cell.getKey(), cell.getValue()); 
       }
       Result filteredResult = new Result(listKV);
   }
}

(此代码未经过测试)

然后最后filteredResult就是你想要的。这种方法并不优雅,如果这些系列中有大量数据,也可能会给您带来性能问题。如果“colfam1”包含大量数据,如果值“x”不在“colfam2”的限定符中,则不希望将其传输到客户端。

服务器端过滤。这需要您实现自己的Filter类。我相信您不能使用提供的过滤器类型来执行此操作。实现自己的Filter需要一些工作,您还需要将其编译为.jar并使其可供所有RegionServers使用。但是,它可以帮助您避免徒劳地发送大量“colfam1”数据。 向我展示如何自定义实现过滤器是太多的工作,因此我建议您阅读一本好书(例如HBase: The Definitive Guide)。但是,Filter代码看起来非常像我向您展示的客户端过滤,因此完成了一半的工作。