package cn.songjq.bigdata.hbase.filter;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.InterruptedIOException;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.HBaseConfiguration;

import org.apache.hadoop.hbase.HColumnDescriptor;

import org.apache.hadoop.hbase.HTableDescriptor;

import org.apache.hadoop.hbase.MasterNotRunningException;

import org.apache.hadoop.hbase.TableName;

import org.apache.hadoop.hbase.ZooKeeperConnectionException;

import org.apache.hadoop.hbase.client.HBaseAdmin;

import org.apache.hadoop.hbase.client.HTable;

import org.apache.hadoop.hbase.client.Put;

import org.apache.hadoop.hbase.client.Result;

import org.apache.hadoop.hbase.client.ResultScanner;

import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;

import org.apache.hadoop.hbase.client.Scan;

import org.apache.hadoop.hbase.filter.BinaryComparator;

import org.apache.hadoop.hbase.filter.BinaryPrefixComparator;

import org.apache.hadoop.hbase.filter.ByteArrayComparable;

import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;

import org.apache.hadoop.hbase.filter.ColumnRangeFilter;

import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;

import org.apache.hadoop.hbase.filter.FamilyFilter;

import org.apache.hadoop.hbase.filter.FilterList;

import org.apache.hadoop.hbase.filter.FilterList.Operator;

import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;

import org.apache.hadoop.hbase.filter.InclusiveStopFilter;

import org.apache.hadoop.hbase.filter.MultipleColumnPrefixFilter;

import org.apache.hadoop.hbase.filter.PageFilter;

import org.apache.hadoop.hbase.filter.QualifierFilter;

import org.apache.hadoop.hbase.filter.RegexStringComparator;

import org.apache.hadoop.hbase.filter.RowFilter;

import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter;

import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;

import org.apache.hadoop.hbase.filter.SubstringComparator;

import org.apache.hadoop.hbase.filter.ValueFilter;

import org.apache.hadoop.hbase.util.Bytes;

import org.junit.Before;

import org.junit.Test;

/**

* HBase过滤器操作,主要介绍以下几种过滤器和比较器

1、列值过滤器:SingleColumnValueFilter,SingleColumnValueExcludeFilter等

2、行健过滤器: RowFilter ,RandomRowFilter等

3、键值元数据过滤器:FamilyFilter,QualifierFilter,ColumnPrefixFilter ,MultipleColumnPrefixFilter,ColumnRangeFilter等

4、功能过滤器:PageFilter,FirstKeyOnlyFilter,InclusiveStopFilter等

5、组合多个过滤器:

  HBase比较器:

   1、正则表达式比较器:RegexStringComparator

   2、字串比较器:SubStringComparator

   3、前缀二进制比较器:BinaryPrefixComparator

   4、二进制比较器:BinaryComparator

 

* @author songjq

*

*/

public class HBaseFilterDemo {

//HBase数据库连接对象

private HBaseAdmin hbaseAdmin = null;

//HBase 表连接对象

private static HTable hTable = null;

/**

* 数据准备

* 进行过滤器操作前,需要将Emp表数据插入到HBase中

* @throws IOException

* @throws ZooKeeperConnectionException

* @throws MasterNotRunningException

*/

@Before

public void init() throws MasterNotRunningException, ZooKeeperConnectionException, IOException {

//获取HBase数据库连接对象

Configuration conf = HBaseConfiguration.create();

conf.set("hbase.zookeeper.quorum", "hadoop-server01:2181,hadoop-server02:2181,hadoop-server03:2181");

hbaseAdmin = new HBaseAdmin(conf);

if(!hbaseAdmin.tableExists("emp")) {

//表不存在,创建表,并初始化表的数据

TableName tableName = TableName.valueOf("emp");

//表描述符

HTableDescriptor empTable = new HTableDescriptor(tableName);

//列描述符

HColumnDescriptor f1 = new HColumnDescriptor("empinfo");

//保留3个版本数据

f1.setMaxVersions(3);

empTable.addFamily(f1);

hbaseAdmin.createTable(empTable);

//初始化数据

hTable = new HTable(conf, "emp");

HBaseFilterDemo.putDataToEmp();

}else {

//表存在,直接获取表的对象

hTable = new HTable(conf, "emp");

}

}

/**

* 插入数据

* @throws IOException

* @throws RetriesExhaustedWithDetailsException

*/

public static void putDataToEmp() throws RetriesExhaustedWithDetailsException, IOException {

List<Put> puts = new ArrayList<>();

//构造一个数据流,emp表的csv文件

FileInputStream filein = new FileInputStream("D:\\test\\hbase\\emp.csv");

InputStreamReader fileinReader = new InputStreamReader(filein);

BufferedReader br = new BufferedReader(fileinReader);

String line = null;

while((line=br.readLine())!=null) {

//得到一行数据

String[] split = line.split(",");

//7499,ALLEN,SALESMAN,7698,1981/2/20,1600,300,30

int empno = Integer.valueOf(split[0]);

String ename = split[1];

String job = split[2];

int mgr = 0;

try {

mgr = Integer.valueOf(split[3]);

}catch (Exception e) {

mgr = 0;

}

String hiredate = split[4];

float salary = Float.valueOf(split[5]);

float comm = 0f;

try {

comm = Float.valueOf(split[6]);

}catch (Exception e) {

comm = 0f;

}

int deptno = Integer.valueOf(split[7]);

//行键rowkey

Put put = new Put(Bytes.toBytes(empno));

//列族

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"), Bytes.toBytes(ename));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("job"), Bytes.toBytes(job));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("mgr"), Bytes.toBytes(mgr));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("hiredate"), Bytes.toBytes(hiredate));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("salary"), Bytes.toBytes(salary));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("comm"), Bytes.toBytes(comm));

put.add(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"), Bytes.toBytes(deptno));

puts.add(put);

}

hTable.put(puts);

br.close();

fileinReader.close();

filein.close();

}

/**

* 列值过滤器SingleColumnValueFilter

* 输出结果(薪水 >=3000的员工信息)

*  SCOTT 3000.0 20

KING 5000.0 10

FORD 3000.0 20

Lili 3212.0 20

John 4521.0 30

Jack 3421.0 20

Jimy 5000.0 10

Bill 3242.0 20

Harry 4215.0 20

* @throws Exception

*/

@Test

public void testSingleColumnValueFilter() throws Exception {

Scan scan = new Scan();

/*

* new SingleColumnValueFilter(  family 列族名称

*  qualifier 列名称

*  compareOp 比较条件

*  value 比较值);

*/

//CompareOp.GREATER_OR_EQUAL:>= ,这里是获取Salary>=3000f的员工信息,类似关心数据库select * from emp where salay>=6000;

SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes("empinfo"),

Bytes.toBytes("salary"), CompareOp.GREATER_OR_EQUAL, Bytes.toBytes(3000f));

scan.setFilter(singleColumnValueFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 列名前缀过滤器 ColumnPrefixFilter,值获取制定的列 ,非必要列不获取,这样可以提高HBase中数据查询效率和提高网络传输效率

* 改过滤器只能获取单列信息

* 执行结果(获取列名以en开头的所有列信息,由于emp表en开头的只有ename列,所以只有一列匹配)

*  SMITH

ALLEN

WARD

...

Gaze

Harry

Goodle

* @throws Exception

*/

@Test

public void testColumnPrefixFilter() throws Exception {

Scan scan = new Scan();

//获取列名以en开头的所有列信息

ColumnPrefixFilter columnPrefixFilter = new ColumnPrefixFilter(Bytes.toBytes("en"));

scan.setFilter(columnPrefixFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"))));

}

hTable.close();

}

/**

* 多个列名前缀过滤器: MultipleColumnPrefixFilter,可以一次性获取多个列前缀匹配信息

* 执行结果(Bytes.toBytes("en"),Bytes.toBytes("sal"),Bytes.toBytes("dep"),查询匹配列名称前缀匹配en,sal,dep的所有列信息

* 这里,匹配了ename,salary,deptno三列)

*  SMITH 800.0 20

ALLEN 1600.0 30

WARD 1250.0 30

JONES 2975.0 20

MARTIN 1250.0 30

...

Bill 3242.0 20

Gaze 1234.0 30

Harry 4215.0 20

Goodle 1300.0 10

* @throws Exception

*/

@Test

public void testMultipleColumnPrefixFilter() throws Exception {

Scan scan = new Scan();

//byte[][] arg0这里是一个二维数据,因此可以一次性指定多个列查询,这里指定了3列,类似关系型数据库select ename,salary,deptno from emp;

byte[][] multiCol = {Bytes.toBytes("en"),Bytes.toBytes("sal"),Bytes.toBytes("dep")};

MultipleColumnPrefixFilter mulColfilter = new MultipleColumnPrefixFilter(multiCol);

scan.setFilter(mulColfilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* rowkey 过滤器,根据行键rowkey进行查询

* RowFilter(CompareOp rowCompareOp 比较规则

* ByteArrayComparable rowComparator 匹配的正则表达式new RegexStringComparator(String args)

* )

* 执行结果:(rowkey>=8130)

*  8130 Jack 3421.0 20

8131 Jimy 5000.0 10

8132 Michal 1500.0 30

8133 Bill 3242.0 20

8134 Gaze 1234.0 30

8135 Harry 4215.0 20

8136 Goodle 1300.0 10

* @throws Exception

*/

@Test

public void testRowkeyFilter() throws Exception {

Scan scan = new Scan();

//查询行键大于8130 类似关系型数据库select * from emp where empno>= 8130;

ByteArrayComparable rowComparator = new BinaryComparator(Bytes.toBytes(8130));

RowFilter rowFilter = new RowFilter(CompareOp.GREATER_OR_EQUAL, rowComparator);

scan.setFilter(rowFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 基于正则表达式的查询

* RegexStringComparator

* 执行结果:(ename以S结尾员工信息)

*  7566 JONES 2975.0 20

7876 ADAMS 1100.0 20

7900 JAMES 950.0 30

* @throws Exception

*

*/

@Test

public void testRegexStringComparator() throws Exception {

Scan scan = new Scan();

//查询以ename以S结尾员工信息 类似关系型数据库select * from emp where ename like '%S';

RegexStringComparator regex = new RegexStringComparator(".*S$");

SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"), CompareOp.EQUAL, regex);

scan.setFilter(singleColumnValueFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 子串比较器:SubStringComparator,用于监测一个子串是否存在于值中,并且不区分大小写。

* 执行结果(查询ename包含AM的员工信息):

*  7876 ADAMS 1100.0 20

7900 JAMES 950.0 30

8129 Abama 2450.0 10

* @throws Exception

*/

@Test

public void testSubStringComparator() throws Exception {

Scan scan = new Scan();

//查询ename包含AM的员工信息 类似关系型数据库select * from emp where upper(ename) like '%AM%';

SubstringComparator substrComp = new SubstringComparator("AM");

SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"), CompareOp.EQUAL, substrComp);

scan.setFilter(singleColumnValueFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 前缀二进制比较器:BinaryPrefixComparator,与二进制比较器不同的是,只比较前缀是否相同

* 执行结果:(查询ename以A开头的行)

*  7499 ALLEN 1600.0 30

7876 ADAMS 1100.0 20

8129 Abama 2450.0 10

* @throws Exception

*

*/

@Test

public void testBinaryPrefixComparator() throws Exception {

Scan scan = new Scan();

//查询ename以A开头的员工信息 类似关系型数据库select * from emp where ename like 'A%';

BinaryPrefixComparator comp = new BinaryPrefixComparator(Bytes.toBytes("A")); //

SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"),  CompareOp.EQUAL, comp);

scan.setFilter(filter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* SingleColumnValueExcludeFilter:跟 SingleColumnValueFilter 功能一样,只是不查询出该列的值

* 执行结果:(不查询ename列的值,如下为空)

* 7788 null 3000.0 20

* @throws Exception

*/

@Test

public void SingleColumnValueExcludeFilter() throws Exception {

Scan scan = new Scan();

SingleColumnValueExcludeFilter filter = new SingleColumnValueExcludeFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"),  CompareOp.EQUAL, Bytes.toBytes("SCOTT"));

scan.setFilter(filter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 列族过滤器:FamilyFilter,用于过滤列族(通常在 Scan 过程中通过设定某些列族来实现该功能,而不是直接使用该过滤器)

* 执行结果:(查询empinfo列族信息)

*  7369 SMITH 800.0 20

7499 ALLEN 1600.0 30

7521 WARD 1250.0 30

...

8134 Gaze 1234.0 30

8135 Harry 4215.0 20

8136 Goodle 1300.0 10

* @throws Exception

*

*/

@Test

public void testFamilyFilter() throws Exception {

Scan scan = new Scan();

//只查询empinfo列族的信息

FamilyFilter familyFilter = new FamilyFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("empinfo")));

scan.setFilter(familyFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

/**

* 列名(Qualifier)过滤器:QualifierFilter,用于列名(Qualifier)过滤。

* @throws Exception

*/

@Test

public void testQualifierFilter() throws Exception {

Scan scan = new Scan();

//只查询emp表的ename列,类似select ename from emp;

QualifierFilter qualifierFilter = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("ename")));

scan.setFilter(qualifierFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"))));

}

hTable.close();

}

/**

* 列名范围过滤器:ColumnRangeFilter,该过滤器可以进行高效的列名内部扫描。(为何是高效呢???因为列名是已经按字典排序好的)HBase-0.9.2 版本引入该功能。

* 执行结果,查询(ename,salary]之间的所有列信息,由于不包含ename列,所以ename列值查询为null:

*  7369 null 800.0

7499 null 1600.0

7521 null 1250.0

...

7844 null 1500.0

7876 null 1100.0

* @throws Exception

*/

@Test

public void testColumnRangeFilter() throws Exception {

Scan scan = new Scan();

/*

* minColumn:最小列名

* minColumnInclusive:是否包含最小列名

* maxColumn:最大列名

* maxColumnInclusive:是否包含最大列名

*/

//查询列名以ename开头,但不包含ename列,以salary结尾,包含salary列的所有列信息,也就是列名称按照字典顺序在(ename,salary]之间的所有列信息

ColumnRangeFilter columnRangeFilter = new ColumnRangeFilter(Bytes.toBytes("ename"), false, Bytes.toBytes("salary"), true);

scan.setFilter(columnRangeFilter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary"))));

}

hTable.close();

}

/**

* PageFilter:分页过滤器,用于按行分页

* 执行结果,分页查询,每页10条记录:

*  这是第1页

7369 SMITH 800.0

7499 ALLEN 1600.0

7521 WARD 1250.0

7566 JONES 2975.0

7654 MARTIN 1250.0

7698 BLAKE 2850.0

7782 CLARK 2450.0

7788 SCOTT 3000.0

7839 KING 5000.0

7844 TURNER 1500.0

这是第2页

7876 ADAMS 1100.0

7900 JAMES 950.0

7902 FORD 3000.0

7934 MILLER 1300.0

8123 Mary 800.0

8124 Tom 1600.0

8125 Lucy 1250.0

8126 Lili 3212.0

8127 Jim 1250.0

8128 John 4521.0

这是第3页

8129 Abama 2450.0

8130 Jack 3421.0

8131 Jimy 5000.0

8132 Michal 1500.0

8133 Bill 3242.0

8134 Gaze 1234.0

8135 Harry 4215.0

8136 Goodle 1300.0

总页数 : 4,总记录数:28

* @throws Exception

*/

@Test

public void testPageFilter() throws Exception {

long pageSize = 10;

int totalRowsCount = 0;

int pageNum = 0;

PageFilter filter = new PageFilter(pageSize);

byte[] lastRow = null;

while(true) {

Scan scan = new Scan();

scan.setFilter(filter);

if(lastRow != null) {

 byte[] postfix = Bytes.toBytes("postfix");

 byte[] startRow = Bytes.add(lastRow, postfix);

 scan.setStartRow(startRow);

 //System.out.println("start row : " + Bytes.toString(startRow));

}

ResultScanner scanner = hTable.getScanner(scan);

int localRowsCount = 0;

if(localRowsCount%10==0) {

System.out.println();

pageNum++;

System.out.println("这是第"+pageNum+"页");

}

for(Result emp : scanner) {

 localRowsCount++;

 totalRowsCount++;

 lastRow = emp.getRow(); // ResultScanner 的结果集是排序好的,这样就可以取到最后一个 row 了

 System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary"))));

}

scanner.close();

if(localRowsCount == 0) break;

}

System.out.println("总页数 : "+pageNum+",总记录数:"+totalRowsCount);

}

/**

* FirstKeyOnlyFilter:该过滤器只查询每个行键的第一个键值对,在统计计数的时候提高效率。(HBase-Coprocessor 做 RowCount 的时候可以提高效率)。

* @throws Exception

*/

@Test

public void testFirstKeyOnlyFilter() throws Exception {

Scan scan = new Scan();

FirstKeyOnlyFilter filter = new FirstKeyOnlyFilter(); // 只查询每个行键的第一个键值对

scan.setFilter(filter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//查询记录数

int counter = 0;

while(it.hasNext()) {

counter++;

}

System.out.println(counter);

hTable.close();

}

/**

* InclusiveStopFilter:常规的 Scan 包含 start-row 但不包含 stop-row,如果使用该过滤器便可以包含 stop-row。

* 执行结果:(查询行键范围为[7876,8125]的员工信息),如下包含了stop—row

*  7876 ADAMS 1100.0

7900 JAMES 950.0

7902 FORD 3000.0

7934 MILLER 1300.0

8123 Mary 800.0

8124 Tom 1600.0

8125 Lucy 1250.0

* @throws Exception

*/

@Test

public void testInclusiveStopFilter() throws Exception {

//Scan scan = new Scan(Bytes.toBytes(7876),Bytes.toBytes(8125));--不会包含8125

Scan scan = new Scan(Bytes.toBytes(7876));

InclusiveStopFilter filter = new InclusiveStopFilter(Bytes.toBytes(8125));

scan.setFilter(filter);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary"))));

}

hTable.close();

}

/**

* 组合比较器:将多个比较器组合使用,实现更复杂的查询条件

* 实现功能:查询薪水大于3000,且只查询ename,salary,deptno三列,且员工名称以J开头的员工

* 类似于关系型数据库select ename,salary,deptno from emp where salary>3000 and deptno=20;

* 执行结果:可以看出我们输出了job列,但是查询条件不包括job列,所以job列为空

*  8128 John 4521.0 null 30

8130 Jack 3421.0 null 20

8131 Jimy 5000.0 null 10

* @throws Exception

*/

@Test

public void testCombinationFilter() throws Exception {

Scan scan = new Scan();

//这里需要3个过滤器才能实现

//第一个过滤器,薪水>3000的员工

SingleColumnValueFilter filter1 = new SingleColumnValueFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("salary"), CompareOp.GREATER, Bytes.toBytes(3000f));

//第二个过滤器,查询ename以J开头的员工

BinaryPrefixComparator comp = new BinaryPrefixComparator(Bytes.toBytes("J")); //

SingleColumnValueFilter filter2 = new SingleColumnValueFilter(Bytes.toBytes("empinfo"), Bytes.toBytes("ename"),  CompareOp.EQUAL, comp);

//第三个过滤器,只查询3列ename,salary,deptno

byte[][] arrs = {Bytes.toBytes("ename"),Bytes.toBytes("salary"),Bytes.toBytes("deptno")};

MultipleColumnPrefixFilter filter3 = new MultipleColumnPrefixFilter(arrs);

//创建一个过滤器list,对象主要有MUST_PASS_ALL:表示满足所有条件,类似关系型数据库AND。MUST_PASS_ONE:表示满足一个条件即可,类似于OR

FilterList filterList = new FilterList(Operator.MUST_PASS_ALL);

//将3个过滤器添加到filterList

filterList.addFilter(filter1);

filterList.addFilter(filter2);

filterList.addFilter(filter3);

scan.setFilter(filterList);

ResultScanner rs = hTable.getScanner(scan);

Iterator<Result> it = rs.iterator();

//打印结果

while(it.hasNext()) {

Result emp = it.next();

System.out.println(Bytes.toInt(emp.getRow())+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("ename")))+"\t"+

  Bytes.toFloat(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("salary")))+"\t"+

  Bytes.toString(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("job")))+"\t"+

  Bytes.toInt(emp.getValue(Bytes.toBytes("empinfo"), Bytes.toBytes("deptno"))));

}

hTable.close();

}

}