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

Lindorm:JSONデータ型

最終更新日:Jan 14, 2025

LindormTableでは、テーブルの作成、データの挿入、データの更新時にJSONデータを使用できます。JSONデータ型は、さまざまなプログラミング言語でデータ交換のために広く使用されています。JSONデータは、キーと値のペアに基づく明確な構造を採用しており、読みやすく、送信しやすい形式です。

適用可能なエンジン

JSONデータはLindormTableにのみ適用されます。

前提条件

LindormTableのバージョンが 2.6.2 以降である必要があります。 LindormTableのバージョンを確認またはアップグレードする方法の詳細については、LindormTableのリリースノートおよびLindormインスタンスのマイナーエンジンバージョンのアップグレードをご参照ください。

制限事項

Lindormワイドテーブルのプライマリキー列のデータ型をJSONに設定することはできません。

DDL

テーブルを作成したり、テーブルに列を追加したりするときに、特定の列のデータ型をJSONに設定できます。

  • 次のステートメントを実行して、テーブルを作成し、テーブル内の列のデータ型をJSONに設定できます。テーブルの作成に使用される構文の詳細については、CREATE TABLEをご参照ください。

    CREATE TABLE tb (p1 INT, c1 VARCHAR, c2 JSON, PRIMARY KEY(p1));
  • 次のステートメントを実行して、c3列をテーブルに追加し、c3列のデータ型をJSONに設定できます。テーブルへの列の追加に使用される構文の詳細については、ALTER TABLEをご参照ください。

    ALTER TABLE tb ADD c3 JSON;
    説明

    テーブルに列を追加しても、テーブルはロックされません。テーブルに対してDML操作を実行できます。

上記の例では、tbテーブルには、データ型がINTのプライマリキー列p1、データ型がVARCHARの非プライマリキー列c1、テーブルの作成時にデータ型がJSONに設定された非プライマリキー列c2、およびc3列がテーブルに追加されたときにデータ型がJSONに設定された非プライマリキー列c3が含まれています。次のステートメントを実行して、tbテーブルのスキーマをクエリできます。

DESCRIBE tb;

返された結果:

+--------------+---------------------+------------------------+---------+----------------+------------+
| TABLE_SCHEMA |     TABLE_NAME      |      COLUMN_NAME       |  TYPE   | IS_PRIMARY_KEY | SORT_ORDER |
+--------------+---------------------+------------------------+---------+----------------+------------+
| default      | tb                  | p1                     | INT     | true           | ASC        |
| default      | tb                  | c1                     | VARCHAR | false          | none       |
| default      | tb                  | c2                     | JSON    | false          | none       |
| default      | tb                  | c3                     | JSON    | false          | none       |
+--------------+---------------------+------------------------+---------+----------------+------------+

DML

DML操作を実行して、データ型がJSONの列にデータを書き込んだり、データを読み取ったり、データを削除したりできます。

UPSERT

次の3つの方法のいずれかを使用して、JSON列にデータを書き込むことができます。JSONオブジェクトまたはJSON文字列のみを、データ型がJSONの列に書き込むことができます。それ以外の場合、データを書き込むときにエラーが発生します。LindormTable SQLは、json_object関数とjson_array関数を用意しており、テーブルに書き込まれるデータをJSONオブジェクトに変換できます。

  • JSON列にJSON文字列を書き込みます。次の方法を使用して、JSON文字列をJSON列に書き込むことができます。

    • Statement()メソッドを使用してSQLステートメントを実行します。この方法で、JSON文字列をJSON列に書き込むことができます。

      Connection conn = DriverManager.getConnection("Lindorm URL", properties);
      Statement stmt = conn.createStatement();
      String jsonStr1 = "{\"k1\":4,\"k2\":{\"k3\":{\"k4\":4}}}"; 
      String upsertSQL = "UPSERT INTO tb(p1, c1, c2) VALUES(1, '1', '"+ jsonStr1 + "')"; 
      // テーブルに書き込まれる列の数を返します。
      int ret = stmt.executeUpdate(upsertSQL);
    • PrepareStatement()メソッドを使用してSQLステートメントを実行します。この方法では、SQLステートメントが前処理され、SQLテンプレートのパラメーターに値が指定されます。

      String jsonStr1 = "{\"k1\":4,\"k2\":{\"k3\":{\"k4\":4}}}";
      // データの書き込みに使用するSQLテンプレートを指定します。
      String upsertSQL = "UPSERT INTO tb(p1, c1, c2) VALUES(1, '1', ?)";
      PreparedStatement preStmt = conn.prepareStatement(upsertSQL);
      // JSON文字列をJSON列に書き込みます。
      preStmt.setString(1, jsonStr1);
      int ret = stmt.executeUpdate();
  • json_object関数を使用して、書き込まれたデータを書き込み順に基づいてキーと値のペアで構成されるJSONオブジェクトに変換し、JSONオブジェクトをJSON列に書き込みます。

    String upsert = "UPSERT INTO tb(p1,c1,c2) VALUES(2,'2',json_object('k1', 2, 'k2', '2'))";

    LindormTable SQLを使用して、上記のステートメントで指定されたデータを書き込むには、次のステートメントを実行します。

    UPSERT INTO tb(p1,c1,c2) VALUES(2,'2','{"k1":2,"k2":"2"}');
  • json_array関数を使用して、書き込まれたデータを書き込み順に基づいて配列形式のJSONオブジェクトに変換し、JSONオブジェクトをJSON列に書き込みます。

    String  upsert = "UPSERT INTO " + tableName + "(p1,c1,c2) VALUES(3,'3', json_array(1, 2, json_object('k1', 3, 'k2', '3')))";

    LindormTable SQLを使用して、上記のステートメントで指定されたデータを書き込むには、次のステートメントを実行します。

    UPSERT INTO tb(p1,c1,c2) VALUES(3,'3','[1,2,{"k1":3,"k2":"3"}]');

結果の確認

次のステートメントを実行して、テーブルに書き込まれたデータを表示します。

SELECT * FROM tb;

SELECT

JSON列の値をクエリする場合、json_extract関数を使用して値を返すか、条件を設定して値をフィルタリングする必要があります。

LindormTable SQLのjson_extract関数は、MySQLの関数と同様に使用できます。json_extract関数は、SELECT句またはWHERE句で使用できます。

  • json_extract関数がSELECT句で使用される場合、関数はJSON列の値を取得し、値をユーザーに返します。例:

    • JSON列に次のデータを書き込みます:"{\"k1\":1}"

      String json = "{\"k1\":1}";
      // SELECT句で json_extract 関数を使用して、c2 列の k1 の値を返し、結果を格納する列の名前を j に設定します。
      String select = "select p1, c1, c2, json_extract(c2, '$.k1') j from tb where p1 = 1";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。
      String resultC2k1 = resultSet.getString("j");
      // resultC2k1 は c2 列の k1 の値(1)を示します。
    • JSON列に次のデータを書き込みます:"{\"k1\":2,\"k2\":\"2\"}"

      String json ="{\"k1\":2,\"k2\":\"2\"}";
      // SELECT句で json_extract 関数を使用して、c2 列の k2 の値を返し、結果を格納する列の名前を j に設定します。
      String select =  "select p1, c1, c2, json_extract(c2, '$.k2') j from tb where p1 = 2";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。
      String resultC2k1 = resultSet.getString("j");
      // resultC2k1 は c2 列の k2 の値(2)を示します。
    • JSON列に次のデータを書き込みます:"[1,2,{\"k1\":3,\"k2\":\"3\"}]"

      String json ="[1,2,{\"k1\":3,\"k2\":\"3\"}]";
      // SELECT句で json_extract 関数を使用して、c2 列のJSON配列の2番目のインデックスにある k2 の値を返し、結果を格納する列の名前を j に設定します。
      String "select json_extract(c2, '$[2].k2') j from  tb where p1 = 3";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。
      String resultC2k1 = resultSet.getString("j");
      // resultC2k1 は c2 列のJSON配列の2番目のインデックスにある k2 の値(3)を示します。
  • json_extract関数がWHERE句で使用される場合、関数はJSON列の値を取得し、値をフィルタリングします。json_extract関数がWHERE句でデータの比較とフィルタリングに使用される場合、LindormTable SQLで異なるタイプのデータを比較するために使用されるメソッドは、MySQLで使用されるメソッドと同じです。詳細については、JSONデータ型をご参照ください。

    • JSON列に次のデータを書き込みます:"{\"k1\":2,\"k2\":\"2\"}"

      String json =  "{\"k1\":2,\"k2\":\"2\"}";
      // WHERE句で json_extract 関数を使用して、c2 列の k2 の値が 0 より大きいデータ行を返します。
      String select = "select p1, c1, c2 from tb where where p1 >= 1 and p1 < 4 and json_extract(c2, '$.k2') > '0'";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。
    • JSON列に次のデータを書き込みます:"{\"k1\":4,\"k2\":{\"k3\":{\"k4\":4}}}"

      String json = "{\"k1\":4,\"k2\":{\"k3\":{\"k4\":4}}}";
      // WHERE句で json_extract 関数を使用して、c2 列の '$.k2.k3.k4' パスの値が 4 より大きいデータ行を返します。
      String select = "select * from tb where p1 >= 4 and p1 < 6 and json_extract(c2, '$.k2.k3.k4') > 4";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。
    • JSON列に次のデータを書き込みます:"[1,2,{\"k1\":3,\"k2\":\"3\"}]"

      String json = "[1,2,{\"k1\":3,\"k2\":\"3\"}]";
      // WHERE句で json_extract 関数を使用して、c2 列のJSON配列の2番目のインデックスにある k2 の値が 0 より大きいデータ行を返します。
      String select = "select * from  tb where p1 >= 1 and p1 < 4 and json_extract(c2, '$[2].k2') > '0'";
      ResultSet resultSet = stmt.executeQuery(select);
      resultSet.next();
      String resultC2 = resultSet.getString(c2);
      // resultC2 は c2 列を示します。

UPDATE

重要

UPDATEステートメントを実行するために使用されるパスは、マップ形式である必要があります。たとえば、c2列のk1パスの値が2の場合、k1パスの値を更新することはできません。 c2列のk1パスの値が{"k2":"value"}の場合、k1パスの値を更新できます。 UPDATEステートメントを実行する前に、UPSERT INTOステートメントを実行して、元のパス値を有効な形式の新しい値で上書きできます。

JSON列の指定されたパスのデータを更新するには、UPDATE構文を使用する必要があります。 UPDATE構文は、次の操作をサポートしています。

  • JSON_SET:JSON列の指定されたパスの値を更新するか、JSON列の新しいパスとパスの値を追加します。

    例:c2列にk1.k2パスが存在する場合、k1.k2パスの値はvalueに更新されます。 c2列にk1.k2パスが存在しない場合、k1.k2パスが追加され、その値はvalueに設定されます。 k1.k2パスを追加する前に、k1パスが存在することを確認してください。

    UPDATE tb SET c2 = JSON_SET(c2, '$.k1.k2', 'value') WHERE p1 = 2;
  • JSON_INERT:JSON列に存在しないパスに値を追加します。

    例:c2列にk1.k2パスが存在しない場合、k1.k2パスの値はnvalueに設定されます。パスに値を追加する前に、k1パスが存在することを確認してください。

    UPDATE tb SET c2 = JSON_INSERT(c2 ,'$.k1.k2' ,'nvalue') WHERE p1 = 2;
  • JSON_REPLACE:JSON列の既存のパスの値を更新します。

    例:c2列にk1パスが存在する場合、k1パスの値はnvalueに更新されます。

    UPDATE tb SET c2 = JSON_REPLACE(c2 ,'$.k1' ,'nvalue') WHERE p1 = 2;
  • JSON_REMOVE:JSON列の既存のパスとパスの値を削除します。

    例:c2列にk1パスが存在する場合、k1パスとパスの値が削除されます。

    UPDATE tb SET c2 = JSON_REMOVE(c2 , '$.k1') WHERE p1 = 2;

結果の確認

次のステートメントを実行して、更新されたデータを表示します。

SELECT * FROM tb;

セカンダリインデックスの作成

LindormTable SQLでは、JSON列の指定されたパスのデータのセカンダリインデックスを作成できます。セカンダリインデックスを作成するときに、json_extract関数の型を指定する必要があります。

構文

create_index_statement ::=  CREATE INDEX [ index_name ]
                                ON table_name '(' index_identifier ')'
                              [INCLUDE include_identifier]
                              [ASYNC]
                                 [ index_options ]
index_identifier       ::=  '('json_extract_type(column, json_path)')'
include_identifier   ::= '('column_name1,...,column_namen ')'

パラメーター

パラメーター

説明

index_name

インデックステーブルの名前。

table_name

ワイドテーブルの名前。

json_extract_type

指定されたデータ型のフィールドをJSON列から抽出してセカンダリインデックスを作成するために使用されるjson_extract関数の型。JSON列のデータの型がjson_extract関数の型と一致しない場合、セカンダリインデックスは作成されません。有効な値:

  • json_extract_string

  • json_extract_long

column

JSON列の名前。

json_path

JSON列のパス。インデックスの作成に使用される値は、パスから抽出されます。

ASYNC

検索インデックスが非同期で作成されることを指定します。このパラメーターを指定しない場合、検索インデックスは同期的に作成されます。

c3列のk1.k2パスのLONGデータのセカンダリインデックスを作成し、インデックステーブルの圧縮アルゴリズムをZSTDに設定します。 k1.k2パスのデータがLONG型でない場合、セカンダリインデックスは作成されません。 k1.k2パスのデータがLONG型でない場合、セカンダリインデックスは作成されません。

CREATE INDEX idx1 ON tb(json_extract_long(c2, '$.k1.k2')) INCLUDE(c1,c3) ASYNC 'COMPRESSION'='ZSTD';

結果の確認

次のステートメントを実行して、作成されたインデックスを表示します。

SHOW INDEX FROM tb;