多元索引支援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),包含province、city、street三個地址層級欄位(均為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 SDK、Go SDK和Python SDK使用JSON類型。