すべてのプロダクト
Search
ドキュメントセンター

Tablestore:ルートフィールドの使い方

最終更新日:Apr 28, 2025

検索インデックスを作成する際に、1 つ以上のプライマリキー列をルートフィールドとして指定できます。インデックスデータが検索インデックスに書き込まれると、Tablestore はルートフィールドの値に基づいてインデックスデータが分散される場所を決定します。ルートフィールドの値が同じ行は、同じパーティションにインデックス化されます。

手順

  1. 検索インデックスを作成する際に、1 つ以上のルートフィールドを指定します。

    検索インデックスの作成時にルートフィールドを指定すると、データの読み取りおよび書き込み操作のために、ルートフィールドを使用してインデックスデータが特定されます。

    検索インデックスのスキーマを動的に変更して、検索インデックスのルートフィールドを動的に変更できます。たとえば、検索インデックスのスキーマを動的に変更して、デフォルトのルートフィールドをカスタムルートフィールドに変更したり、カスタムルートフィールドをデフォルトのルートフィールドに変更したりできます。デフォルトのルートフィールドはパーティションキーです。詳細については、「検索インデックスのスキーマを動的に変更する」をご参照ください。

    重要

    Tablestore のプライマリキー列のみをルートフィールドとして指定できます。ほとんどの場合、指定する必要があるルートフィールドは 1 つだけです。複数のルートフィールドを指定すると、システムはルートフィールドの値を連結して 1 つの値としてルートキーを作成します。

  2. 検索インデックスを使用してデータをクエリする際に、クエリリクエストでルートフィールドを指定します。

    Tablestore は、クエリリクエストで指定したルートフィールドに基づいて、指定されたパーティションのみをスキャンします。これにより、Tablestore がスキャンするパーティションが絞り込まれるため、クエリレイテンシが短縮されます。検索インデックスにルートフィールドを指定した場合は、検索インデックスを使用してデータをクエリする際に、ルートフィールドを指定する必要があります。検索インデックスにルートフィールドを指定するかどうかは、検索インデックスを使用してデータをクエリする際のクエリ結果には影響しません。ただし、ルートフィールドを指定しないと、Tablestore は無関係なパーティションをスキャンします。これはシステムリソースの無駄になり、クエリレイテンシが増加します。

    重要

    ルートフィールドには、1 つ以上の値を指定できます。ただし、ルートフィールドの値の範囲を指定することはできません。

方法

Tablestore コンソールでルートフィールドを指定するか、Tablestore CLI または Tablestore SDK を使用できます。検索インデックスの作成時、または既存の検索インデックスのルートフィールドの変更時に、ルートフィールドを指定できます。このセクションでは、検索インデックスの作成時にルートフィールドを指定する方法の例を示します。次の項目では、検索インデックスのルートフィールドを指定する前に満たす必要がある前提条件について説明します。

説明

検索インデックスを作成した後、検索インデックスのスキーマを変更して、検索インデックスのルートフィールドを変更できます。詳細については、「検索インデックスのスキーマを動的に変更する」をご参照ください。

  • 以下の条件を同時に満たす データテーブル が作成されます。

    • データテーブルの「バージョンの最大数」パラメータが 1 に設定されています。

    • データテーブルの Time To Live(TTL)が -1 に設定されているか、データテーブルの更新操作が禁止されています。

  • Tablestore SDK を使用してルートフィールドを指定する場合は、クライアントが初期化されます。詳細については、「Tablestore クライアントを初期化する」をご参照ください。

  • Tablestore CLI を使用してルートフィールドを指定する場合は、Tablestore CLI がインストールされて起動され、アクセスするインスタンスの情報が構成されています。詳細については、「Tablestore CLI をダウンロードする」および「Tablestore CLI を起動し、アクセス情報を構成する」をご参照ください。

Tablestore コンソールの使用

Tablestore コンソール で検索インデックスを作成する際に、[詳細設定] をオンにして、次の図に示すようにルートフィールドを指定します。詳細については、「手順 1: 検索インデックスを作成する」をご参照ください。

image

Tablestore CLI の使用

Tablestore CLI を使用して create_search_index コマンドを実行し、検索インデックスを作成できます。詳細については、「検索インデックス」をご参照ください。

  1. 検索インデックスを作成する際に、ルートフィールドを指定します。

    次のサンプルコードは、mysearchindex という名前の検索インデックスを作成する方法の例を示しています。検索インデックスには、LONG 型の gid フィールド、LONG 型の uid フィールド、LONG 型の col2 フィールド、TEXT 型の col3 フィールド、KEYWORD 型の col1 フィールド、LONG 型の col3V フィールドが含まれています。 col3V フィールドは、データテーブルの col3 列に対応する仮想カラムです。この例では、検索インデックスのルートフィールドは uid フィールドです。

    create_search_index -n mysearchindex

    画面の指示に従って、検索インデックスのスキーマを指定します。検索インデックスを使用してデータをクエリする前に、ビジネス要件に基づいてサンプルコードのフィールド設定を変更する必要があります。サンプルコード:

    {
    
        "IndexSetting": {
            "RoutingFields": ["uid"] // ルートフィールドを指定
        },
        "FieldSchemas": [
        {
            "FieldName": "gid",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "uid",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
    
    // 中略
    
    }
  2. 検索インデックスを使用してデータをクエリする際に、ルートフィールドを指定します。

    次のサンプルコードは、mysearchindex 検索インデックスを使用して、col2 列の値が 200 未満の行をクエリする方法の例を示しています。データをクエリする際には、検索インデックスのルートフィールドを指定する必要があります。この例では、ルートフィールドは uid です。

    search -n search_index --return_all_indexed

    画面の指示に従って、クエリ条件を指定します。検索インデックスを使用してデータをクエリする前に、ビジネス要件に基づいてサンプルコードのクエリ条件を変更する必要があります。サンプルコード:

    説明

    この例では、範囲クエリメソッドを使用しています。検索インデックス機能でサポートされているクエリメソッドについては、「基本機能」をご参照ください。

    {
        "Offset": -1,
        "Limit": 10,
        "Collapse": null,
        "Sort": null,
        "GetTotalCount": true,
        "Token": null,
    	  "IndexSetting": {
            "RoutingFields": ["uid"] // ルートフィールドを指定
        },
        "Query": {
            "Name": "RangeQuery",
            "Query": {
                "FieldName": "col2",
                "From": null,
                "To": 200,
                "IncludeLower": false,
                "IncludeUpper": false
             }
         }
    }

Tablestore SDK の使用

次の Tablestore SDK を使用して、検索インデックスの作成時にルートフィールドを指定できます。Tablestore SDK for JavaTablestore SDK for GoTablestore SDK for PythonTablestore SDK for Node.jsTablestore SDK for .NETTablestore SDK for PHP。この例では、Tablestore SDK for Java を使用して、ルートフィールドを指定および使用する方法について説明します。

次のサンプルコードは、order という名前のデータテーブルを作成し、user_id フィールドをルートフィールドに設定し、データテーブルにデータを書き込み、クエリリクエストでルートフィールドを提供する方法の例を示しています。この例では、データテーブルには STRING 型の order_id プライマリキー列と STRING 型の user_id プライマリキー列が含まれています。 多次元インデックスには、KEYWORD 型の product_name フィールド、LONG 型の order_time フィールド、および KEYWORD 型の user_id フィールドが含まれています。

private static void testRoute(SyncClient client) throws InterruptedException {
    // テーブルを作成します。
    TableMeta meta = new TableMeta("order");
    meta.addPrimaryKeyColumn("order_id",PrimaryKeyType.STRING);
    meta.addPrimaryKeyColumn("user_id",PrimaryKeyType.STRING);
    TableOptions options = new TableOptions();
    options.setMaxVersions(1);
    options.setTimeToLive(-1);
    CreateTableRequest request = new CreateTableRequest(meta,options);
    request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
    CreateTableResponse response = client.createTable(request);

    // 検索インデックスを作成し、ルーティングフィールドを指定します。
    CreateSearchIndexRequest searchIndexRequest = new CreateSearchIndexRequest();
    // データテーブルの名前を指定します。
    searchIndexRequest.setTableName("order"); 
    // データテーブルに作成される検索インデックスの名前を指定します。
    searchIndexRequest.setIndexName("order_index"); 
    IndexSchema indexSchema = new IndexSchema();
    IndexSetting indexSetting = new IndexSetting();
    // ルーティングフィールドを user_id フィールドに設定します。
    indexSetting.setRoutingFields(Arrays.asList("user_id"));
    indexSchema.setIndexSetting(indexSetting);

    // インデックスフィールドを追加します。以下のインデックスフィールドは参考までに追加されています。ビジネス要件に基づいてインデックスフィールドを追加できます。
    indexSchema.setFieldSchemas(Arrays.asList(
        new FieldSchema("product_name",FieldType.KEYWORD).setStore(true).setIndex(true),
        new FieldSchema("order_time",FieldType.LONG).setStore(true).setEnableSortAndAgg(true).setIndex(true),
        new FieldSchema("user_id",FieldType.KEYWORD).setStore(true).setIndex(true)
    ));

    searchIndexRequest.setIndexSchema(indexSchema);
    client.createSearchIndex(searchIndexRequest);
    // データテーブルがロードされるまで待機します。
    Thread.sleep(6*1000); 

    // テスト用のデータを挿入します。

    String[] productName = new String[]{"product a", "product b", "product c"};
    String[] userId = new String[]{"00001", "00002", "00003", "00004", "00005"};
    for (int i = 0; i < 100; i++){

      PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
      primaryKeyBuilder.addPrimaryKeyColumn("order_id",PrimaryKeyValue.fromString(i+""));
      primaryKeyBuilder.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString(userId[i%(userId.length)]));
      PrimaryKey primaryKey = primaryKeyBuilder.build();

      RowPutChange rowPutChange = new RowPutChange("order",primaryKey);

      // 属性列にデータを書き込みます。
      rowPutChange.addColumn("product_name",ColumnValue.fromString(productName[i%(productName.length)]));
      rowPutChange.addColumn("order_time",ColumnValue.fromLong(System.currentTimeMillis()));
      rowPutChange.setCondition(new Condition(RowExistenceExpectation.IGNORE));

      client.putRow(new PutRowRequest(rowPutChange));

    }
    // データが検索インデックスに同期されるまで待機します。
    Thread.sleep(20*1000);

    // クエリリクエストでルーティングフィールドを提供します。
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setTableName("order");
    searchRequest.setIndexName("order_index");
    MatchQuery matchQuery = new MatchQuery();
    matchQuery.setFieldName("user_id");
    matchQuery.setText("00002");
    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(matchQuery);
    searchQuery.setGetTotalCount(true);

    SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
    columnsToGet.setReturnAll(true);
    searchRequest.setColumnsToGet(columnsToGet);
    searchRequest.setSearchQuery(searchQuery);

    PrimaryKeyBuilder pkbuild = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pkbuild.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString("00002"));
    PrimaryKey routingValue = pkbuild.build();
    searchRequest.setRoutingValues(Arrays.asList(routingValue));
    SearchResponse searchResponse = client.search(searchRequest);

    System.out.println(searchResponse.isAllSuccess());
    System.out.println("totalCount:"+ searchResponse.getTotalCount());
    System.out.println("RowCount:"+searchResponse.getRows().size());

  }