查询后过滤

查询后过滤(Filter)是表格存储多元索引(Search Index)新增的一种查询辅助功能,支持对 Query 结果再做一次过滤。该功能的目的主要是人工干预内部的查询优化器,强制某些查询条件在最后阶段执行,使用合理,可以大幅提高查询性能。

说明

Java SDK5.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

SearchRequestSearchQuery的查询过滤参数配置

  • query(必选) Query:主查询条件配置,支持多元索引的所有查询类型。包含以下参数:

    名称

    数据类型

    说明

    type(必选)

    QueryType

    查询类型。支持Search接口的全部查询类型,不推荐使用MatchAllQuery。

    query(必选)

    bytes

    查询条件。

  • filter(可选) SearchFilter:二次过滤配置,对主查询结果进行精细化筛选。包含以下参数:

    • query(必选) Query:过滤查询条件配置,仅支持特定查询类型。包含以下参数:

      名称

      数据类型

      说明

      type(必选)

      QueryType

      查询类型,仅支持TermQuery、TermsQuery、RangeQueryExistsQuery及这些查询类型组成的BoolQuery。

      query(必选)

      bytes

      查询条件。

示例代码

以下示例演示如何使用查询后过滤功能:先通过主查询条件匹配col_keyword字段值为"value"的数据,然后使用过滤条件筛选col_long字段值在110之间的记录。

  • 命令式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());
        }
    }