All Products
Search
Document Center

Tablestore:Array and nested data types

Last Updated:Jun 20, 2026

Search indexes support the Array and Nested data types in addition to primitive types such as Long, Double, Boolean, Keyword, Text, Date, GeoPoint, Vector, IP, and JSON. Use the Array type to store multiple values of the same type, and the Nested type to store hierarchical data similar to JSON.

Array data type

Important
  • The Array data type applies only to search indexes. Data tables do not support the Array data type.

  • Query an Array field the same way as a non-Array field. A row is returned if at least one value in the array meets the query condition.

  • The Vector data type does not support arrays.

The Array type is a modifier that combines with primitive types such as Long, Double, Boolean, Keyword, Text, Date, IP, and GeoPoint. For example, combining the Array type with the Long type creates a long integer array that stores multiple long integers.

Array formats

The following table describes the array formats for primitive data types in search indexes.

Array type

Description

Long Array

An array of long integers. Example: "[1000, 4, 5555]".

Double Array

An array of floating-point numbers. Example: "[3.1415926, 0.99]".

Boolean Array

An array of Boolean values. Example: "[true, false]".

Keyword Array

An array of strings in JSON format. Example: "[\"Hangzhou\", \"Xi'an\"]".

Text Array

An array of text in JSON format. Example: "[\"Hangzhou\", \"Xi'an\"]".

Text arrays are rarely used.

Date Array

An array of dates. If the date type is an integer, the format is "[1218197720123, 1712850436000]". If the date type is a string, the format is "[\"2024-04-11 23:47:16.854775807\", \"2024-06-11 23:47:16.854775807\"]".

IP Array

An array of IP addresses in JSON format. Example: "[\"192,168.1.1\", \"255.255.255.255\"]".

Geopoint Array

An array of geographic points. Example: "[\"34.2, 43.0\", \"21.4, 45.2\"]".

Usage notes

For Array-type fields in a search index, the corresponding field in the data table must be of the String type, and the field in the search index must be of the corresponding primitive type, such as Long or Double.

For example, if the price field is a Double Array type, the price field in the data table must be of the String type. In the search index, set the field type to Double and add the isArray=true property.

Examples

Assume that a data table named array_search_table contains the following sample data.

The data table includes the primary key column pk (String type) and two attribute columns: col_keyword_array (String type) and col_long_array (String type).

pk

col_keyword_array

col_long_array

03#server#07

["Development environment", "Test environment", "Physical server", "Linux" ]

[2020, 2023]

4c#server#ae

["Production environment", "Cloud server", "Linux" ]

[2021, 2024]

  1. Create a search index.

    Create a search index named array_query_table_index. The index includes two columns: col_keyword_array (String Array type) and col_long_array (Long Array type).

    For Schema Generation Method, select Auto-generate. Then, in the field configuration table, verify that the Array toggle is enabled for the corresponding fields.

  2. Query Array-type data by using the search index.

    The following Java code queries array data where the col_keyword_array column contains an element that exactly matches "Cloud server" and the col_long_array column contains an element equal to 2024.

    Note

    To query Array-type data in a search index by using SQL statements, see Execute SQL statements to query data using the search index.

    private static void query(SyncClient client) {
        // Condition 1: The col_keyword_array field contains an element that is an exact match for "ECS".
        TermQuery keywordTermQuery = new TermQuery(); 
        keywordTermQuery.setFieldName("col_keyword_array"); 
        keywordTermQuery.setTerm(ColumnValue.fromString("ECS")); 
        // Condition 2: The col_long_array field contains an element equal to 2024.
        TermQuery longTermQuery = new TermQuery(); 
        longTermQuery.setFieldName("col_long_array"); 
        longTermQuery.setTerm(ColumnValue.fromLong(2024l)); 
        SearchQuery searchQuery = new SearchQuery();
        // Require both conditions to be true.
        BoolQuery boolQuery = new BoolQuery();
        boolQuery.setMustQueries(Arrays.asList(keywordTermQuery, longTermQuery));
        searchQuery.setQuery(boolQuery);
        //searchQuery.setGetTotalCount(true); // Set to return the total number of matched rows.
        SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
        // You can configure the columnsToGet parameter to specify the columns to return or return all columns. If this parameter is not configured, only primary key columns are returned by default.
        //SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
        //columnsToGet.setReturnAll(true); // Set to return all columns.
        //columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Set to return specified columns.
        //searchRequest.setColumnsToGet(columnsToGet);
        SearchResponse resp = client.search(searchRequest);
        //System.out.println("TotalCount: " + resp.getTotalCount()); // Print the total number of matched rows, not the number of returned rows.
        System.out.println("Row: " + resp.getRows());
    }

Nested data type

The Nested type represents nested documents. A row of data (document) can contain multiple child rows (child documents) stored in a nested field. The Nested type is suitable for storing hierarchical data.

Specify the schema of child rows in a nested field, including the fields and properties of each child row. The Nested type supports multiple values and is similar to the JSON data type.

Nested formats

Nested fields are classified into single-level and multi-level types.

Nesting type

Description

Single-level nested type

Contains one layer of nested data structure with a basic hierarchy. Suitable for scenarios that need simple parent-child relationships without multiple levels. Example:

[
    {
        "tagName": "tag1",
        "score": 0.8
    },
    {
        "tagName": "tag2",
        "score": 0.2
    }
]

Multi-level nested type

Contains multiple layers of nested data structures with a complex hierarchy. Suitable for data models that require rich hierarchies and a high degree of modularity. Example:

[
    {
        "name": "Zhang San",
        "age": 20,
        "phone": "1390000****",
        "address": [
            {
                "province": "Zhejiang Province",
                "city": "Hangzhou City",
                "street": "No. 1201, Xingfu Community, Sunshine Avenue"
            }
        ]
    }
]

Usage notes

For Nested-type fields in a search index, the corresponding field in the data table must be of the String type, and the field in the search index must be of the Nested type. Use nested queries to query Nested-type fields.

When writing data to the data table, format the nested field value as a JSON array of objects. For example, [{"tagName":"tag1", "score":0.8,"time": 1730690237000 }, {"tagName":"tag2", "score":0.2,"time": 1730691557000}].

Important

Always write data as a JSON array string to a nested field, even if the field contains only one child row.

Examples

Example of single-level Nested fields

Create a single-level Nested field in the Tablestore console or by using a Tablestore SDK.

The following Java code example shows how to create a nested field named tags. The child rows contain the following three fields.

  • Field name: tagName. Field type: Keyword.

  • Field name: score. Field type: Double.

  • Field name: time. Field type: Date. Unit: milliseconds.

Sample data written to the data table is [{"tagName":"tag1", "score":0.8,"time": 1730690237000 }, {"tagName":"tag2", "score":0.2,"time": 1730691557000}].

// Create FieldSchema objects for the fields in a child row.
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")));
// Set the child row FieldSchema objects to the subFieldSchemas of the nested field.
FieldSchema nestedFieldSchema = new FieldSchema("tags", FieldType.NESTED)
    .setSubFieldSchemas(subFieldSchemas);

Example of multiple-level Nested fields

Create a multi-level Nested field by using a Tablestore SDK.

The following example uses Tablestore SDK for Java to create a Nested field named user. Each child row contains four primitive-type fields and one Nested field.

  • Field name: name. Field type: Keyword.

  • Field name: age. Field type: Long.

  • Field name: birth. Field type: Date. Value format: date string.

  • Field name: phone. Field type: Keyword.

  • Nested field name: address. Child row fields: province, city, and street. Data type: Keyword for all fields.

Sample data to write to the data table: [ {"name":"Zhang San","age":20,"birth":"2014-10-10 12:00:00.000","phone":"1390000****","address":[{"province":"Zhejiang Province","city":"Hangzhou City","street":"No. 1201, Xingfu Community, Sunshine Avenue"}]}]

// Define subfield schemas for the 'address' nested field. The query path for these fields is 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));
// Define subfield schemas for the 'user' nested field. Each child row contains four primitive type fields and one nested field 'address'.
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.NESTED).setSubFieldSchemas(addressSubFiledSchemas));
// Add the 'user' nested field schema to the list of main field schemas.
List<FieldSchema> fieldSchemas = new ArrayList<>();
fieldSchemas.add(new FieldSchema("user",FieldType.NESTED).setSubFieldSchemas(subFieldSchemas));

Limits

  • Search indexes that contain Nested fields do not support IndexSort, a feature that improves query performance in various scenarios.

  • When paginating query results from a search index that contains Nested fields, specify a sort method in the query conditions. Otherwise, Tablestore does not return nextToken when only partial results are read.

  • Nested queries provide lower performance than other types of queries.

Apart from these limits, the Nested type supports all query types, sorting, and aggregation.

References