查询后过滤(Filter)是表格存储多元索引(Search Index)新增的一种查询辅助功能,支持对 Query 结果再做一次过滤。该功能的目的主要是人工干预内部的查询优化器,强制某些查询条件在最后阶段执行,使用合理,可以大幅提高查询性能。
Java SDK从5.17.5版本开始支持查询后过滤功能,如需使用请加入钉钉群36165029092(表格存储技术交流群-3)联系表格存储技术支持开通。
功能架构
查询后过滤基于多层查询架构实现:
SearchRequest:查询请求的顶层容器,包含表名、索引名和具体的查询配置。
SearchQuery:核心查询配置,包含主查询条件(Query)和可选的查询过滤器(SearchFilter)。
Query:主查询条件,支持多元索引的所有查询类型和数据类型,用于初次数据检索。
SearchFilter:二次过滤器,包含过滤查询条件,在主查询结果基础上进行精细化筛选。
使用限制
必须与多元索引查询条件组合使用,支持精确查询(TermQuery)、多词精确查询(TermsQuery)、范围查询(RangeQuery)、列存在性查询(ExistsQuery)及其组合查询(BoolQuery)。
BoolQuery 查询时,仅支持必须匹配(mustQueries)、必须不匹配(mustNotQueries)、可选匹配(shouldQueries)子句,不支持过滤子句(filterQueries)。
仅支持对不可分词字符串(Keyword)、长整型(Long)、双精度浮点型(Double)字段进行过滤,且字段必须启用排序统计(enableSortAndAgg)属性。
查询后过滤不支持设置权重。
前提条件
在数据表上创建多元索引。
方法说明
public SearchResponse search(SearchRequest searchRequest) throws TableStoreException, ClientException示例代码
以下示例演示如何使用查询后过滤功能:先通过主查询条件匹配col_keyword字段值为"value"的数据,然后使用过滤条件筛选col_long字段值在1到10之间的记录。
命令式API调用方式
private static void queryUsingSetter(SyncClient client) { //【必须修改】替换为数据表名称 String tableName = "<TABLE_NAME>"; //【必须修改】替换为多元索引名称 String indexName = "<SEARCH_INDEX_NAME>"; // 构建主查询:terms精确匹配 TermsQuery termsQuery = new TermsQuery(); termsQuery.setFieldName("col_keyword"); termsQuery.addTerm(ColumnValue.fromString("value")); // 构建过滤条件:col_long 字段取值范围 (1, 10) RangeQuery rangeQuery = new RangeQuery(); rangeQuery.setFieldName("col_long"); rangeQuery.setFrom(ColumnValue.fromLong(1)); rangeQuery.setTo(ColumnValue.fromLong(10)); // 组装 Filter SearchFilter searchFilter = new SearchFilter(); searchFilter.setQuery(rangeQuery); // 组合完整 SearchQuery SearchQuery searchQuery = new SearchQuery(); searchQuery.setQuery(termsQuery); searchQuery.setFilter(searchFilter); // 构造请求 SearchRequest searchRequest = new SearchRequest(tableName, indexName, searchQuery); // 系统默认只返回主键列,请按需设置返回的列 SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet(); // 设置返回多元索引中的所有列 columnsToGet.setReturnAllFromIndex(true); searchRequest.setColumnsToGet(columnsToGet); try { SearchResponse resp = client.search(searchRequest); System.out.println("Rows: " + resp.getRows()); } catch (Exception e) { System.err.println("Search failed: " + e.getMessage()); } }按需配置返回指定列或所有列
SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet(); // 返回指定列 columnsToGet.setColumns(Arrays.asList("col_long", "col_keyword")); // 指定列 // 或者:返回所有列 // columnsToGet.setReturnAll(true); searchRequest.setColumnsToGet(columnsToGet);如需统计匹配总行数,请开启totalCount统计功能后在返回结果中打印即可。
// 在searchQuery中配置开启totalCount统计 searchQuery.setTrackTotalCount(SearchQuery.TRACK_TOTAL_COUNT); // 在结果中打印总行数 System.out.println("Total Count (matched): " + resp.getTotalCount());
构建器模式API调用方式
private static void queryUsingBuilder(SyncClient client) { //【必须修改】替换为数据表名称 String tableName = "<TABLE_NAME>"; //【必须修改】替换为多元索引名称 String indexName = "<SEARCH_INDEX_NAME>"; try { // 构建 SearchQuery:主查询和过滤条件 SearchQuery searchQuery = SearchQuery.newBuilder() .query(QueryBuilders.terms("col_keyword").terms("value")) // 精确匹配关键词 .filter(SearchFilter.newBuilder() .query(QueryBuilders.range("col_long") .greaterThan(1) // (1, 10) 区间 .lessThan(10)) .build()) // .trackTotalCount(SearchQuery.TRACK_TOTAL_COUNT) // 按需开启统计总匹配数 .build(); // 构造请求 SearchRequest searchRequest = new SearchRequest(tableName, indexName, searchQuery); // 系统默认只返回主键列,请按需设置返回的列。 SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet(); // 设置返回多元索引中的所有列 columnsToGet.setReturnAllFromIndex(true); searchRequest.setColumnsToGet(columnsToGet); SearchResponse resp = client.search(searchRequest); System.out.println("Rows: " + resp.getRows()); } catch (Exception e) { System.err.println("Search request failed: " + e.getMessage()); } }