全部产品
Search
文档中心

表格存储:JSON类型

更新时间:Dec 05, 2025

多元索引支持JSON类型字段,通过高效存储和灵活查询半结构化数据,解决日志分析、用户行为记录、配置管理等复杂业务场景中嵌套数据结构的检索与分析需求,显著提升查询效率和数据处理准确性。

重要

如需使用多元索引JSON类型,请联系表格存储技术支持开通。

工作原理

通过将数据表中的String类型字段映射到多元索引的JSON类型字段,支持具有层级结构的半结构化数据处理,针对不同业务查询需求和性能要求,提供Object类型Nested类型两种JSON存储模式。

  • Object类型:采用扁平化存储策略,将嵌套结构转换为平级字段,适用于对查询性能要求较高的简单字段检索场景。

  • Nested类型:维持嵌套对象的独立性和字段关联关系,适用于需要精确匹配对象内字段组合的复杂查询场景。

核心区别

两种JSON类型在数据处理方式、查询语法、字段关联性和性能特点方面存在显著差异:

  • 数据处理方式:Object类型将嵌套数据扁平化存储,Nested类型将每个嵌套对象作为独立文档存储。

  • 查询方式:Object类型使用基础查询,Nested类型必须使用NestedQuery查询。

  • 字段关联性:Object类型允许不同嵌套对象的字段交叉匹配,Nested类型确保每个嵌套对象内的字段独立匹配。

  • 性能特点:Object类型查询轻量高效,资源消耗低,Nested类型功能强大但资源消耗相对较高。

选择原则

当业务查询需要严格保持嵌套对象内字段的关联性和准确性时,选择Nested类型;当追求高查询性能且对字段关联性要求不严格时,优先选择Object类型。

配置和使用JSON类型索引

通过完整的JSON类型字段索引配置流程,从类型选择、索引创建到查询验证,为半结构化数据建立高效可靠的检索体系。

无论JSON类型选择Object还是Nested,都必须为所有子字段明确定义字段类型,未定义类型的字段将被索引系统忽略,无法参与查询。

步骤一:选择JSON类型和数据格式

根据具体的业务查询需求、性能要求和数据结构特点,选择最适合的JSON类型和数据写入格式。

JSON类型选择策略
  • Object类型:适用于简单字段独立查询,提供优异的查询性能和较低的资源消耗。

  • Nested类型:适用于需要维护字段关联性的精确查询,确保查询结果的准确性。

  • 混合使用:Object和Nested类型支持在同一索引中灵活组合,满足复杂业务场景需求。

数据写入格式规范

JSON字段支持数组格式和非数组格式两种数据写入方式,根据业务数据结构选择合适的格式:

//数组格式
[{ "country": "China", "city": "hangzhou" }, { "country": "usa", "city": "Seattle" }]

//非数组格式
{ "country": "China", "city": "hangzhou" }
数据写入示例
private static void putRow(SyncClient client) {
    //构造主键。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("10001"));
    PrimaryKey primaryKey = primaryKeyBuilder.build();

    //设置数据表名称。
    RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);

    // 构建JSON原始数据。
    List<Map<String, Object>> addresses = Arrays.asList(
    new HashMap<String, Object>() {{ put("country", "China"); put("city", "hangzhou"); }},
    new HashMap<String, Object>() {{ put("country", "usa");   put("city", "Seattle"); }}
    );
    String jsonString = JSON.toJSONString(addresses); 

    rowPutChange.addColumn(new Column("address", ColumnValue.fromString(jsonString)));

    client.putRow(new PutRowRequest(rowPutChange));
}

步骤二:配置字段结构和创建索引

以包含两个子字段的单层级JSON为例,演示完整的索引配置实现过程。通过合理的字段类型定义和属性设置,确保索引功能的完整性和查询性能的优化。

List<FieldSchema> subFieldSchemas = new ArrayList<FieldSchema>();
subFieldSchemas.add(new FieldSchema("country", FieldType.KEYWORD)
    .setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("city", FieldType.KEYWORD)
    .setIndex(true).setEnableSortAndAgg(true));

FieldSchema jsonFieldSchema = new FieldSchema("address", FieldType.Json)
    .setJsonType(JsonType.OBJECT) // 设置为JsonType.OBJECT或JsonType.NESTED
    .setSubFieldSchemas(subFieldSchemas);

步骤三:查询数据

通过实际的查询测试验证索引配置的正确性,对比Object和Nested两种JSON类型在相同数据和查询条件下的不同查询行为和结果差异。

  • Object类型:将嵌套数据扁平化处理,查询时使用父子字段名通过半角句号连接的路径访问方式。扁平化存储使得不同嵌套对象的字段值可以交叉匹配。

  • Nested类型:保持每个嵌套对象的独立性和完整性,必须使用NestedQuery包装查询条件,确保字段匹配仅在同一嵌套对象内进行。

索引后格式

假设示例数据为address字段的数据为 [{ "country": "China", "city": "hangzhou" }, { "country": "usa", "city": "Seattle" }]。

  • Object类型的JSON索引后格式:{"address.country": ["China", "usa"], "address.city": ["hangzhou","Seattle"]}

  • Nested类型的JSON索引后格式:独立文档{ "country": "China", "city": "hangzhou" }{ "country": "usa", "city": "Seattle" }

由上可知,当查询条件为address.country ="China"address.city="Seattle"时,Object类型的JSON会匹配到数据,Nested类型的JSON无法匹配到数据;当查询条件为address.country ="China"address.city="hangzhou"时,Object类型或Nested类型的JSON均会匹配到数据。

查询示例
JSON Nested类型查询示例

以下示例用于查询address的同一子行能满足address.country为"China"且address.city为"Seattle"两个条件的行数据。

public static void nestedQuery(SyncClient client) {
    // 查询条件一:要求address子行的country列值为"China"
    TermQuery termQuery1 = new TermQuery();
    termQuery1.setFieldName("address.country");
    termQuery1.setTerm(ColumnValue.fromString("China"));

    // 查询条件二:要求address子行的city列值为"Seattle"
    TermQuery termQuery2 = new TermQuery();
    termQuery2.setFieldName("address.city");
    termQuery2.setTerm(ColumnValue.fromString("Seattle"));

    // 通过BoolQuery的And条件,查询同时满足上述条件的子行
    List<Query> mustQueries = new ArrayList<>();
    mustQueries.add(termQuery1);
    mustQueries.add(termQuery2);
    BoolQuery boolQuery = new BoolQuery();
    boolQuery.setMustQueries(mustQueries);

    // NestedQuery内部设置BoolQuery,要求某一子行同时满足多个查询条件
    NestedQuery nestedQuery = new NestedQuery();    //设置查询类型为NestedQuery。
    nestedQuery.setPath("address");   //设置嵌套类型列的路径,即要查询字段的父路径。
    nestedQuery.setQuery(boolQuery);
    nestedQuery.setScoreMode(ScoreMode.None);

    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(nestedQuery);

    SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);

    SearchResponse resp = client.search(searchRequest);
    System.out.println("Row: " + resp.getRows());
}
JSON Object类型查询示例

以下示例用于查询address列的多个子行满足address.country为"China"且address.city为"Seattle"两个条件的行数据。

public static void boolQuery(SyncClient client) {
    // 查询条件一:要求address子行的country列值为"China"
    TermQuery termQuery1 = new TermQuery();
    termQuery1.setFieldName("address.country");
    termQuery1.setTerm(ColumnValue.fromString("China"));

    // 查询条件二:要求address子行的city列值为"Seattle"
    TermQuery termQuery2 = new TermQuery();
    termQuery2.setFieldName("address.city");
    termQuery2.setTerm(ColumnValue.fromString("Seattle"));

    // 通过BoolQuery的And条件,查询同时满足上述条件的子行
    List<Query> mustQueries = new ArrayList<>();
    mustQueries.add(termQuery1);
    mustQueries.add(termQuery2);
    BoolQuery boolQuery = new BoolQuery();
    boolQuery.setMustQueries(mustQueries);


    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(boolQuery);

    SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);

    SearchResponse resp = client.search(searchRequest);
    System.out.println("Row: " + resp.getRows());
}

JSON类型应用示例

无论JSON类型选择Object还是Nested,单层级与多层级的Schema配置结构保持一致,仅在类型设置上有所区别,便于灵活切换和统一管理。

单层级JSON示例

以Java代码为例,创建单层级JSON字段tags(可根据需求选择JSON类型),包含以下三个功能字段:

  • tagName:字符串类型(Keyword),用于标签名称的精确匹配和聚合分析。

  • score:浮点数类型(Double),用于标签权重的数值计算和排序。

  • time:日期时间类型(Date),采用毫秒时间戳格式,用于时间范围查询和时序分析。

数据写入时支持数组和非数组两种格式,可根据业务数据结构灵活选择:

// 数组形式
[{"tagName":"tag1", "score":0.8,"time": 1730690237000 }, {"tagName":"tag2", "score":0.2,"time": 1730691557000}]
// 非数组形式
{"tagName":"tag1", "score":0.8,"time": 1730690237000 }

完整的Schema配置代码实现:

List<FieldSchema> subFieldSchemas = new ArrayList<FieldSchema>();
subFieldSchemas.add(new FieldSchema("tagName", FieldType.KEYWORD)
    .setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("score", FieldType.DOUBLE)
    .setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("time", FieldType.DATE)
    .setDateFormats(Arrays.asList("epoch_millis")));

FieldSchema nestedFieldSchema = new FieldSchema("tags", FieldType.Json)
    .setJsonType(JsonType.OBJECT) // 按需替换为JsonType.NESTED
    .setSubFieldSchemas(subFieldSchemas);

多层级JSON示例

以Java代码为例,创建多层级JSON字段user(可根据需求设置JsonType),构建包含基础用户信息和嵌套地址信息的完整数据结构。使用多层级JSON时支持混合使用Nested类型和Object类型。

  • 基础字段:name(Keyword类型,用于姓名精确查询)、age(Long类型,用于年龄范围筛选)、birth(Date类型,格式为yyyy-MM-dd HH:mm:ss.SSS,用于生日时间查询)、phone(Keyword类型,用于联系方式匹配)。

  • 嵌套字段address(可根据需求设置JsonType),包含provincecitystreet三个地址层级字段(均为Keyword类型),支持地理位置的层级查询。

典型的用户数据写入示例:

{
  "name": "张三",
  "age": 20,
  "birth": "2014-10-10 12:00:00.000",
  "phone": "1390000****",
  "address": {
    "province": "浙江省",
    "city": "杭州市",
    "street": "阳光大道幸福小区1201号"
  }
}

多层级JSON的完整Schema配置实现:

// address子字段Schema(路径:user.address)
List<FieldSchema> addressSubFiledSchemas = new ArrayList<>();
addressSubFiledSchemas.add(new FieldSchema("province",FieldType.KEYWORD));
addressSubFiledSchemas.add(new FieldSchema("city",FieldType.KEYWORD));
addressSubFiledSchemas.add(new FieldSchema("street",FieldType.KEYWORD));

// user子字段Schema(路径:user)
List<FieldSchema> subFieldSchemas = new ArrayList<>();
subFieldSchemas.add(new FieldSchema("name",FieldType.KEYWORD));
subFieldSchemas.add(new FieldSchema("age",FieldType.LONG));
subFieldSchemas.add(new FieldSchema("birth",FieldType.DATE)
    .setDateFormats(Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS")));
subFieldSchemas.add(new FieldSchema("phone",FieldType.KEYWORD));
subFieldSchemas.add(new FieldSchema("address",FieldType.JSON)
    .setJsonType(JsonType.NESTED) // 按需替换为JsonType.OBJECT
    .setSubFieldSchemas(addressSubFiledSchemas));

// 创建父字段user
List<FieldSchema> fieldSchemas = new ArrayList<>();
fieldSchemas.add(new FieldSchema("user",FieldType.JSON)
    .setJsonType(JsonType.OBJECT) // 按需替换为JsonType.NESTED
    .setSubFieldSchemas(subFieldSchemas));

配额与限制

JSON类型字段在使用过程中存在以下功能限制和配置要求,需在索引设计时予以考虑:

  • 向量类型限制:向量类型字段无法作为JSON字段的子字段使用,需独立配置向量字段索引。

  • Nested类型限制:当JSON字段类型设置为Nested时,该字段无法使用索引预排序功能,查询时必须使用NestedQuery进行查询。

  • 子字段数组配置要求:当非JSON类型的子字段采用数组格式写入数据时,必须在字段配置中将IsArray属性设置为true,同时确保数据写入格式为`"[a, b, c]"`的标准数组格式,否则该子字段的数据无法被索引正确同步和检索。

开发集成

目前支持通过Java SDKGo SDKPython SDK使用JSON类型。