全部產品
Search
文件中心

Tablestore:JSON類型

更新時間:Dec 06, 2025

多元索引支援JSON類型欄位,通過高效儲存和靈活查詢半結構化資料,解決日誌分析、使用者行為記錄、組態管理等複雜業務情境中嵌套資料結構的檢索與分析需求,顯著提升查詢效率和資料處理準確性。

重要

如需使用多元索引JSON類型,請聯絡Table Store支援人員開通。

工作原理

通過將資料表中的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類型。