使用虚拟列功能时,您可以通过修改多元索引Schema或者新建多元索引来实现新字段新数据类型的查询功能,而无需修改表格存储的存储结构及数据。

解决什么问题

虚拟列功能支持用户在创建多元索引的时候将表中一列映射到多元索引中的虚拟列。新的虚拟列类型可以不同于表中的原始列类型,以便支持用户在不修改表结构和数据的情况下新建一列,新的列可以用于查询加速或者采用不同的分词器。
  • 一个Text字段支持不同的分词器

    单个字符串列可以映射到多元索引多个Text列,不同Text列采用不同的分词,以便满足不同的业务需求。

  • 查询加速

    不对表中数据做清洗和重建,只需要将相应列映射为其他类型,即可在部分场景下提升查询性能。例如数字类型转换为keyword类型可以提高精确查询(TermQuery)的性能,string类型转换为数字类型可以提高范围查询(RangeQuery)的性能。

注意事项

  • 虚拟列支持不同类型到字符串类型的相互转换,转换规则请参见下表。
    数据表中字段类型 虚拟列字段类型
    String Keyword(含数组)
    String Text(含数组)
    String Long(含数组)
    String Double(含数组)
    String Geo-point(含数组)
    Long Keyword
    Long Text
    Double Keyword
    Double Text
  • 虚拟列目前仅支持用在查询语句中,不能用在ColumnsToGet返回列值,如果需要返回列值,可以指定返回该虚拟列的原始列。

通过控制台操作虚拟列

通过控制台在创建多元索引时指定字段为虚拟列后,您可以使用虚拟列查询数据。

  1. 登录表格存储控制台
  2. 概览页面,单击实例名称或在操作列单击实例管理
  3. 实例详情页签的数据表列表区域,单击数据表名称或在操作列单击数据管理后选择索引管理页签。
  4. 索引管理页签,单击创建多元索引
  5. 创建索引对话框,创建多元索引时指定虚拟列。
    fig_indexsearchvitural
    1. 系统默认会自动生成索引名,可根据需要输入索引名
    2. 选择Schema生成方式
      • Schema生成方式设置为手动录入时,手动输入字段名,选择字段类型以及设置是否开启数组。
      • Schema生成方式设置为自动生成时,系统会自动将数据表的主键列和属性列作为索引字段,可根据需要选择字段类型以及设置是否开启数组。
      说明 字段名字段类型需与数据表匹配。数据表字段类型与多元索引字段类型的对应关系请参见字段
    3. 创建虚拟列。
      注意 创建虚拟列时,原始字段名必须在数据表中存在,且原始字段的数据类型必须和虚拟列的字段类型相匹配。
      1. 单击添加索引字段
      2. 输入字段名字段类型
      3. 单击开启虚拟列开关,并输入原始字段名
    4. 单击确定

      多元索引创建完成后,在索引列表的操作列,单击索引详情,可查看索引表的索引计量信息、索引字段等信息。

      fig_searchindex_details
  6. 使用虚拟列查询数据。
    1. 在多元索引的操作列单击搜索
    2. 查询数据对话框,查询数据。
      fig_querdatavirtual
      1. 系统默认返回所有列,如果需要显示指定属性列,关闭获取所有列并输入需要返回的属性列,多个属性列之间用英文逗号(,)隔开。
      2. 选择索引字段,单击添加,并设置索引字段的查询类型和值。
      3. 系统默认关闭排序功能,如需根据索引字段对返回结果进行排序,打开是否排序后,根据需要添加索引字段并配置排序方式。
      4. 单击确定

        符合查询条件的数据会显示在索引管理页签中。

通过SDK操作虚拟列

通过SDK在创建多元索引时指定字段为虚拟列后,您可以使用虚拟列查询数据。

  1. 创建多元索引时指定虚拟列。
    • 参数

      关于参数的详细说明,请参见创建多元索引

    • 示例
      创建一个多元索引,多元索引包含Col_Keyword和Col_Long两列,同时创建虚拟列Col_Keyword_Virtual_Long和Col_Long_Virtual_Keyword。Col_Keyword_Virtual_Long映射为数据表中Col_Keyword列,虚拟列Col_Long_Virtual_Keyword映射为数据表中Col_Long列。
      private static void createSearchIndex(SyncClient client) {
          CreateSearchIndexRequest request = new CreateSearchIndexRequest();
          request.setTableName("tableName"); //设置数据表名称。
          request.setIndexName("indexName"); //设置多元索引名称。
          IndexSchema indexSchema = new IndexSchema();
          indexSchema.setFieldSchemas(Arrays.asList(
              new FieldSchema("Col_Keyword", FieldType.KEYWORD) //设置字段名和类型。
                  .setIndex(true) //设置开启索引。
                  .setEnableSortAndAgg(true) //设置开启排序和统计功能。
                  .setStore(true),
              new FieldSchema("Col_Keyword_Virtual_Long", FieldType.LONG) //设置字段名和类型。
                  .setIndex(true)
                  .setEnableSortAndAgg(true)
                  .setStore(true)
                  .setVirtualField(true) //设置字段是否为虚拟列。
                  .setSourceFieldName("Col_Keyword"), //虚拟列对应的数据表中字段。
              new FieldSchema("Col_Long", FieldType.LONG)
                  .setIndex(true)
                  .setEnableSortAndAgg(true)
                  .setStore(true),
              new FieldSchema("Col_Long_Virtual_Keyword", FieldType.KEYWORD)
                  .setIndex(true)
                  .setEnableSortAndAgg(true)
                  .setStore(true)
                  .setVirtualField(true)
                  .setSourceFieldName("Col_Long")));
          request.setIndexSchema(indexSchema);
          client.createSearchIndex(request); //调用client创建多元索引。
      }
  2. 使用虚拟列查询数据。

    查询表中Col_Long_Virtual_Keyword列的值能够匹配"1000"的数据,返回匹配到的总行数和一些匹配成功的行。

    private static void query(SyncClient client) {
        SearchQuery searchQuery = new SearchQuery();
        TermsQuery termsQuery = new TermsQuery(); //设置查询类型为TermsQuery。
        termsQuery.setFieldName("Col_Long_Virtual_Keyword"); //设置要匹配的字段。
        termsQuery.addTerm(ColumnValue.fromString("1000")); //设置要匹配的值。
        searchQuery.setQuery(termsQuery);
        searchQuery.setGetTotalCount(true); //设置返回匹配的总行数。
        SearchRequest searchRequest = new SearchRequest("tableName", "indexName", searchQuery);
        SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
        columnsToGet.setReturnAll(true); //设置返回所有列,不支持返回虚拟列。
        searchRequest.setColumnsToGet(columnsToGet);
    
        SearchResponse resp = client.search(searchRequest);
        System.out.println("TotalCount: " + resp.getTotalCount()); //匹配到的总行数,非返回行数。
        System.out.println("Row: " + resp.getRows());
    }