目錄:html
引言 -- 參數基礎正則表達式
1. 結構(Structural)過濾器--FilterListapache
2.列值過濾器--SingleColumnValueFilterapi
2.1.第一種構造函數狀況
-- 比較的關鍵字是字符數組數組
2.2.第二種構造函數狀況
-- 比較的關鍵字是比較器ByteArrayComparableide
3.鍵值元數據函數
3.1. 基於列族過濾數據的FamilyFilteroop
3.2. 基於限定符Qualifier(列)過濾數據的QualifierFilter測試
3.3. 基於列名(即Qualifier)前綴過濾數據的ColumnPrefixFilterui
3.4. 基於多個列名(即Qualifier)前綴過濾數據的MultipleColumnPrefixFilter
3.5. 基於列範圍(不是行範圍)過濾數據ColumnRangeFilter
4. RowKey
5. PageFilter
6. SkipFilter
7. Utility--FirstKeyOnlyFilter
8. 取得查詢結果
引言 -- 參數基礎
有兩個參數類在各種Filter中常常出現,統一介紹下:
(1)比較運算符 CompareFilter.CompareOp
比較運算符用於定義比較關係,能夠有如下幾類值供選擇:
EQUAL 相等
GREATER 大於
GREATER_OR_EQUAL 大於等於
LESS 小於
LESS_OR_EQUAL 小於等於
NOT_EQUAL 不等於
(2)比較器 ByteArrayComparable
經過比較器能夠實現多樣化目標匹配效果,比較器有如下子類能夠使用:
BinaryComparator
匹配完整字節數組
BinaryPrefixComparator 匹配字節數組前綴
BitComparator
NullComparator
RegexStringComparator 正則表達式匹配
SubstringComparator 子串匹配
1. 結構(Structural)過濾器--FilterList
FilterList 表明一個過濾器鏈,它能夠包含一組即將應用於目標數據集的過濾器,過濾器間具備「與」 FilterList.Operator.MUST_PASS_ALL 和「或」 FilterList.Operator.MUST_PASS_ONE 關係。
官網實例代碼,兩個「或」關係的過濾器的寫法:
FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE); //數據只要知足一組過濾器中的一個就能夠
SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
Bytes.toBytes("my value")
);
list.add(filter1);
SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
Bytes.toBytes("my other value")
);
list.add(filter2);
Scan scan = new Scan();
scan.setFilter(list);
2. 列值過濾器--SingleColumnValueFilter
SingleColumnValueFilter 用於測試列值相等
(CompareOp.EQUAL ), 不等 (CompareOp.NOT_EQUAL),或單側範圍 (e.g., CompareOp.GREATER)。
構造函數:
(1)比較的關鍵字是一個字符數組
SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, byte[] value)
(2)比較的關鍵字是一個比較器(比較器下一小節作介紹)
SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, ByteArrayComparable comparator)
2.1.第一種構造函數狀況 -- 比較的關鍵字是字符數組
官網示例代碼,檢查列值和字符串'my value' 相等:
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
Bytes.toBytes("my value")
);
scan.setFilter(filter);
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
Bytes.toBytes("2013-06-08")
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
注意:仍是大寫問題,HBase的列名必須大寫!
2.2.第二種構造函數狀況 -- 比較的關鍵字是比較器ByteArrayComparable
該章節主要是針對SingleColumnValueFilter的第二種構造函數使用狀況作了一些舉例:
(1)支持值比較的正則表達式 -- RegexStringComparator
官網示例代碼:
RegexStringComparator comp = new RegexStringComparator("my."); //任意以my打頭的值
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
comp
);
scan.setFilter(filter);
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
RegexStringComparator comp = new RegexStringComparator("2013-06-1.");
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
comp
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
(2)檢測一個子串是否存在於值中(大小寫不敏感) -- SubstringComparator
官網示例代碼:
SubstringComparator comp = new SubstringComparator("y val"); // looking for 'my value'
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
comp
);
scan.setFilter(filter);
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
// RegexStringComparator comp = new RegexStringComparator("2013-06-1.");
SubstringComparator comp = new SubstringComparator("2013-06-1");
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
comp
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
(3)BinaryComparator
二進制比較器,用得較少,有須要請自行查閱官網:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryComparator.html
(4)BinaryPrefixComparator
二進制前綴比較器,用得較少,有須要請自行查閱官網:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.html
3. 鍵值元數據
因爲HBase 採用鍵值對保存內部數據,鍵值元數據過濾器評估一行的鍵(ColumnFamily:Qualifiers)是否存在 ,
對應前節所述值的狀況。
3.1. 基於列族過濾數據的FamilyFilter
構造函數:
FamilyFilter(CompareFilter.CompareOp familyCompareOp, ByteArrayComparable familyComparator)
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* FamilyFilter構造函數中第二個參數是ByteArrayComparable類型
* ByteArrayComparable類參見「引言-參數基礎」章節
* 下面僅以最可能用到的BinaryComparator、BinaryPrefixComparator舉例:
*/
FamilyFilter ff = new FamilyFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("pat")) //表中不存在pat列族,過濾結果爲空
);
FamilyFilter ff1 = new FamilyFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("pat")) //表中存在以pat打頭的列族patentinfo,過濾結果爲該列族全部行
);
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
注意:
若是但願查找的是一個已知的列族,則使用 scan.addFamily(family) 比使用過濾器效率更高;
因爲目前HBase對多列族支持不完善,因此該過濾器目前用途不大。
3.2. 基於限定符Qualifier(列)過濾數據的QualifierFilter
構造函數:
QualifierFilter(CompareFilter.CompareOp op, ByteArrayComparable qualifierComparator)
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* QualifierFilter構造函數中第二個參數是ByteArrayComparable類型
* ByteArrayComparable類有如下子類能夠使用:
* *******************************************
* BinaryComparator 匹配完整字節數組,
* BinaryPrefixComparator 匹配開始的部分字節數組,
* BitComparator,
* NullComparator,
* RegexStringComparator, 正則表達式匹配
* SubstringComparator
* *******************************************
* 下面僅以最可能用到的BinaryComparator、BinaryPrefixComparator舉例:
*/
QualifierFilter ff = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("belong")) //表中不存在belong列,過濾結果爲空
);
QualifierFilter ff1 = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("BELONG")) //表中存在以BELONG打頭的列BELONG_SITE,過濾結果爲全部行的該列數據
);
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
說明:
一旦涉及到列(Qualifier),HBase就只認大寫字母了!
該過濾器應該比FamilyFilter更經常使用!
3.3. 基於列名(即Qualifier)前綴過濾數據的ColumnPrefixFilter
( 該功能用QualifierFilter也能實現 )
構造函數:
ColumnPrefixFilter(byte[] prefix)
注意:
一個列名是能夠出如今多個列族中的,該過濾器將返回全部列族中匹配的列。
官網示例代碼,查找全部"abc"打頭的列:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[] prefix = Bytes.toBytes("abc");
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new ColumnPrefixFilter(prefix);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
//返回全部行中以BELONG打頭的列的數據
ColumnPrefixFilter ff1 = new ColumnPrefixFilter(Bytes.toBytes("BELONG"));
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
3.4. 基於多個列名(即Qualifier)前綴過濾數據的MultipleColumnPrefixFilter
說明:
MultipleColumnPrefixFilter 和 ColumnPrefixFilter 行爲差很少,但能夠指定多個前綴。
官方示例代碼,查找全部"abc"或"xyz"打頭的列:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[][] prefixes = new byte[][] {Bytes.toBytes("abc"), Bytes.toBytes("xyz")};
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new MultipleColumnPrefixFilter(prefixes);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
byte[][] prefixes = new byte[][] {Bytes.toBytes("BELONG"), Bytes.toBytes("CREATE")};
//返回全部行中以BELONG或者CREATE打頭的列的數據
MultipleColumnPrefixFilter ff = new MultipleColumnPrefixFilter(prefixes);
Scan scan = new Scan();
scan.setFilter(ff);
ResultScanner rs = table.getScanner(scan);
3.5. 基於列範圍(不是行範圍)過濾數據ColumnRangeFilter
說明:
可用於得到一個範圍的列,例如,若是你的一行中有百萬個列,可是你只但願查看列名爲bbbb到dddd的範圍
該方法從 HBase 0.92 版本開始引入
一個列名是能夠出如今多個列族中的,該過濾器將返回全部列族中匹配的列
構造函數:
ColumnRangeFilter(byte[] minColumn, boolean minColumnInclusive, byte[] maxColumn, boolean maxColumnInclusive)
參數解釋:
minColumn - 列範圍的最小值,若是爲空,則沒有下限;
minColumnInclusive - 列範圍是否包含minColumn ;
maxColumn - 列範圍最大值,若是爲空,則沒有上限;
maxColumnInclusive - 列範圍是否包含maxColumn 。
官網示例代碼,查找列名在"bbbb"到"dddd"範圍的數據:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[] startColumn = Bytes.toBytes("bbbb");
byte[] endColumn = Bytes.toBytes("bbdd");
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new ColumnRangeFilter(startColumn, true, endColumn, true);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
byte[] startColumn = Bytes.toBytes("C");
byte[] endColumn = Bytes.toBytes("D");
//返回全部列中從C到D打頭的範圍的數據,實際返回相似CREATOR、CREATE_TIME、CHANNEL_CODE等列的數據
ColumnRangeFilter ff = new ColumnRangeFilter(startColumn, true, endColumn, true);
Scan scan = new Scan();
scan.setFilter(ff);
ResultScanner rs = table.getScanner(scan);
4. RowKey
當須要根據行鍵特徵查找一個範圍的行數據時,使用Scan的startRow和stopRow會更高效,可是,startRow和stopRow只能匹配行鍵的開始字符,而不能匹配中間包含的字符:
byte[] startColumn = Bytes.toBytes("aaa");
byte[] endColumn = Bytes.toBytes("bbb");
Scan scan = new Scan(startColumn,endColumn);
當須要針對行鍵進行更復雜的過濾時,能夠使用RowFilter:
構造函數:
RowFilter(CompareFilter.CompareOp rowCompareOp, ByteArrayComparable rowComparator)
參數解釋參見「引言-參數基礎」章節。
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* rowkey格式爲:建立日期_發佈日期_ID_TITLE
* 目標:查找 發佈日期 爲 2013-07-16 的數據
*/
RowFilter rf = new RowFilter(
CompareFilter.CompareOp.EQUAL ,
new SubstringComparator("_2013-07-16_")
);
Scan scan = new Scan();
scan.setFilter(rf);
ResultScanner rs = table.getScanner(scan);
注意:
測試過程當中嘗試經過組合使用兩個RowFilter(CompareFilter.CompareOp參數分別爲GREATER_OR_EQUAL和LESS_OR_EQUAL),和SubstringComparator,過濾找出指定發佈時間範圍內的數據,但結果比較意外,不是預想的數據,估計比較運算符GREATER_OR_EQUAL和LESS_OR_EQUAL和比較器SubstringComparator組合使用效果不太好,慎用。
5.PageFilter
指定頁面行數,返回對應行數的結果集。
須要注意的是,該過濾器並不能保證返回的結果行數小於等於指定的頁面行數,由於過濾器是分別做用到各個region server的,它只能保證當前region返回的結果行數不超過指定頁面行數。
構造函數:
PageFilter(long pageSize)
實測代碼(從「2013-07-26」行開始,取5行):
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("2013-07-26"));
PageFilter pf = new PageFilter(5L);
scan.setFilter(pf);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
注意:
因爲該過濾器並不能保證返回的結果行數小於等於指定的頁面行數,因此更好的返回指定行數的辦法是ResultScanner.next(int
nbRows) ,即:
ResultScanner rs = table.getScanner(scan);
for (Result r : rs.next(5)) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
6.SkipFilter
根據整行中的每一個列來作過濾,只要存在一列不知足條件,整行都被過濾掉。
例如,若是一行中的全部列表明的是不一樣物品的重量,則真實場景下這些數值都必須大於零,咱們但願將那些包含任意列值爲0的行都過濾掉。
在這個狀況下,咱們結合ValueFilter和SkipFilter共同實現該目的:
scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,new BinaryComparator(Bytes.toBytes(0))));
構造函數:
SkipFilter(Filter filter)
我的實測代碼:
目前的數據:
hbase(main):009:0> scan 'rd_ns:itable'
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405417403438, value=anywhere
100001 column=info:age, timestamp=1405417403438, value=24
100001 column=info:name, timestamp=1405417403438, value=zhangtao
100002 column=info:address, timestamp=1405417426693, value=shangdi
100002 column=info:age, timestamp=1405417426693, value=28
100002 column=info:name, timestamp=1405417426693, value=shichao
100003 column=info:address, timestamp=1405494141522, value=huilongguan
100003 column=info:age, timestamp=1405494999631, value=29
100003 column=info:name, timestamp=1405494141522, value=liyang
3 row(s) in 0.0190 seconds
執行如下代碼:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Scan scan = new Scan();
scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,
new BinaryComparator(Bytes.toBytes("28")))));
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
table.close();
輸出結果(整個100002行被過濾掉了):
Rowkey : 100001 Familiy:Quilifier : address Value : anywhere Time : 1405417403438
Rowkey : 100001 Familiy:Quilifier : age Value : 24 Time : 1405417403438
Rowkey : 100001 Familiy:Quilifier : name Value : zhangtao Time : 1405417403438
Rowkey : 100003 Familiy:Quilifier : address Value : huilongguan Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : age Value : 29 Time : 1405494999631
Rowkey : 100003 Familiy:Quilifier : name Value : liyang Time : 1405494141522
7. Utility--FirstKeyOnlyFilter
該過濾器僅僅返回每一行中的第一個cell的值,能夠用於高效的執行行數統計操做。
估計實戰意義不大。
構造函數:
public FirstKeyOnlyFilter()
我的實測代碼:
HTable table = HBaseDAO.getHTable("147patents");
FirstKeyOnlyFilter fkof = new FirstKeyOnlyFilter();
Scan scan = new Scan();
scan.setFilter(fkof);
ResultScanner rs = table.getScanner(scan);
8. 取得查詢結果
不管是官網的Ref Guide仍是網上流傳的大部分博客中,輸出查詢結果的代碼都是:
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
但查看最新的API可知Result實例的raw()方法已經不建議使用了:
raw() Deprecated. as of 0.96, use rawCells()
0.96之後版本正確的獲取結果代碼以下:
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : "+Bytes.toString(r.getRow())+
"Familiy:Quilifier : "+Bytes.toString(CellUtil.cloneQualifier(cell))+
"Value : "+Bytes.toString(CellUtil.cloneValue(cell))
);
}
}
轉載自:http://blog.csdn.net/u010967382/article/details/37653177