MySQL道普請便り

第217回MySQL ShellでJavaScriptを使ってMySQLを操作してみよう[その2]

今回は、前回第216回 MySQL ShellでMySQLをJavaScriptを使って操作してみるで紹介させていただいたMySQL Shellを使ってJavaScriptで操作する方法を、引き続き紹介したいと思います。

検証環境

今回はDockerで建てたMySQLを使用します。以下のコマンドでDockerを建ててローカルからアクセスをします。

% docker run --platform linux/x86_64 -p 127.0.0.1:3307:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_USER=kk2170 -e MYSQL_PASSWORD=my-secret-pw -d mysql:8.0.36

今回も前回や第214回と同様に、DockerのイメージにあるMySQL Shellを使用して接続をしていきます。まずは対話モードでも実行を行いたいので、対話モードでJavaScriptを実行します。

立ち上げたDockerコンテナの中に入るため、コンテナIDを調べます。

$  docker ps
CONTAINER ID   IMAGE                               COMMAND                  CREATED          STATUS
     PORTS                                                 NAMES
5480636b729f   mysql:8.0.36                        "docker-entrypoint.s…"   12 seconds ago   Up 10 seconds
     33060/tcp, 127.0.0.1:3307->3306/tcp                   elastic_lederberg

続いて、docker execコマンドを使用してMySQLのコンテナ内部に入ります。その後、mysqlshコマンドでログインを済ませます。

$ docker exec -it 5480636b729f bash

# mysqlsh
《中略》
 MySQL  localhost  JS >

中略された部分に関して詳細が知りたい場合は、第214回で説明を行っているため、そちらを参照してください。執筆時点では、以下の通りMySQL 8.0.36を使用しております。

 MySQL  localhost  JS > \sql select version();
Fetching global names for auto-completion... Press ^C to stop.
+-----------+
| version() |
+-----------+
| 8.0.36    |
+-----------+
1 row in set (0.0001 sec)

JSONデータを操作してみる

さて今回は前回作成したテーブルに書き込み、読み込み、更新、削除といった基本的なCRUD操作を行っていきます。前回最後に作成したテーブルをもう一度作成してみましょう。

 MySQL  localhost  JS > var mySession = mysqlx.getSession('root:my-secret-pw@localhost');
 MySQL  localhost  JS > mySession.createSchema('test');
<Schema:test>
 MySQL  localhost  JS > mySession.getSchema("test").createCollection("json_table");
<Collection:json_table>

これでtestデータベースにjson_tableというテーブルを用意することができました。

それでは、一旦Collectionのオブジェクトを取得してみて、どのような関数があるのか確認してみましょう。データベースSchemaに対してgetCollectionを行うと、テーブルを取得することができます。

 MySQL  localhost  JS > var table = mySession.getSchema("test").getCollection("json_table");

取得できたtableオブジェクトをObject.keys()の引数にして、どのようなメソッドが生えているか確認してみましょう。

 MySQL  localhost  JS > Object.keys(table);
[
    "name",
    "session",
    "schema",
    "add",
    "addOrReplaceOne",
    "count",
    "createIndex",
    "dropIndex",
    "existsInDatabase",
    "find",
    "getName",
    "getOne",
    "getSchema",
    "getSession",
    "help",
    "modify",
    "remove",
    "removeOne",
    "replaceOne"
]

このようなメソッドが用意されていることがわかります。今回だけでは全部のメソッドに関して説明しきれませんが、便利なメソッドもありますので活用していきましょう。これから基本的なコレクションの操作方法に絞って紹介していきます。

JSONを書き込みして値を確認する

今回は、addメソッドを使って書き込みをしていきます。addメソッドはテーブルに対して行うことで操作が可能となります。

さて、まずは書き込みを行う前に状況を確認してみましょう。データの検索には、findメソッドを使用して確認することができます。引数に入れた値に応じて検索ができるのですが、今回は何も入れずに実行してみます。この場合、WHERE句を付けなかったのと同じ状態になります。

 MySQL  localhost  JS > table.find()
Empty set (0.0005 sec)

テーブルを作ったばかりなので、何も見つかりませんでした。続いて、addメソッドを使ってデータを登録してみましょう。idに1という値を持ったJSONを登録してみます。

 MySQL  localhost  JS > table.add({id: 1})
Query OK, 1 item affected (0.0048 sec)

このデータを取得してみましょう。findメソッドを使って取得してみます。

 MySQL  localhost  test  JS > table.find()
{
    "id": 1,
    "_id": "000065ea84d50000000000000003"
}

_idという値が増えています。これは、テーブル定義にあった主キーとして定義されていた_idが出力されています。今回は指定を行わなかったため自動で生成されていますが、これは自分で定義することもできます。

続いて、同様にaというキーと"test"という値と_idというキーと"primary_key"という値を持つオブジェクトを登録してみましょう。

 MySQL  localhost  test  JS > table.add({a: "test", _id: "primary_key"})
Query OK, 1 item affected (0.0155 sec)
 MySQL  localhost  test  JS > table.find()
{
    "id": 1,
    "_id": "000065ea84d50000000000000003"
}
{
    "a": "test",
    "_id": "primary_key"
}

このように追加できたことがわかります。

格納されているJSONを更新する

続いて更新をしてみましょう。更新にはmodifyメソッドを使います。追加と削除のパターンで、それぞれ考えてみましょう。

"id"が1のオブジェクトに対して"kk2170"という値を持つnameというキーを追加してみましょう。modifyの引数に検索条件を入れることで、特定のオブジェクトに対しての操作を行うことができます。対象に対してsetメソッドをチェーンして、登録したい値を入れることで更新することができます。

 MySQL  localhost  test  JS > table.modify("id = 1").set("name", "kk2170")
 MySQL  localhost  test  JS > table.find("id = 1")
{
    "id": 1,
    "_id": "000065ea84d50000000000000003",
    "name": "kk2170"
}
1 document in set (0.0008 sec)

modifyをして更新した結果が上記になります。今度は、逆に登録したキーを削除してみたいと思います。その場合はunsetが使用できます。

 MySQL  localhost  test  JS > table.modify("id = 1").unset("name")
Query OK, 1 item affected (0.0148 sec)

Rows matched: 1  Changed: 1  Warnings: 0
 MySQL  localhost  test  JS > table.find("id = 1")
{
    "id": 1,
    "_id": "000065ea84d50000000000000003"
}
1 document in set (0.0007 sec)

このように、属性の削除ができていることがわかります。

格納したJSONを削除する

続いてオブジェクト全体を削除してみようと思います。今回使用するのはremoveメソッドになります。removeメソッドも同様に検索条件を引数として渡すことで、オブジェクトの削除を行うことができます。今回はid=1を指定して削除してみましょう。

 MySQL  localhost  test  JS > table.remove("id = 1")
Query OK, 1 item affected (0.0062 sec)
 MySQL  localhost  test  JS > table.find("id = 1")
Empty set (0.0012 sec)

このように削除されていることがわかります。ではデータベースの値全体を削除してみましょう。まずはfindの時のように、引数を空の状態でメソッドを実行してみましょう。

 MySQL  localhost  test  JS > table.remove()
CollectionRemove.remove: Invalid number of arguments, expected 1 but got 0 (ArgumentError)

引数の数が間違っているというエラーが返ってきました。removeを実行するには必ず1つ条件式が必要なようです。ここで思い出すと良いのは、SQLでもWHERE句が常にtrueになる条件式を指定すると、すべての値が取得できるということです。試しにSQLで以下のSQLを実行してみます。

 MySQL  localhost  test  JS > \sql select * from `json_table` where true
+-------------------------------------+--------------------------+--------------------+
| doc                                 | _id                      | _json_schema       |
+-------------------------------------+--------------------------+--------------------+
| {"a": "test", "_id": "primary_key"} | 0x7072696D6172795F6B6579 | {"type": "object"} |
+-------------------------------------+--------------------------+--------------------+
1 row in set (0.0005 sec)
 MySQL  localhost  test  JS > \sql select * from `json_table`
+-------------------------------------+--------------------------+--------------------+
| doc                                 | _id                      | _json_schema       |
+-------------------------------------+--------------------------+--------------------+
| {"a": "test", "_id": "primary_key"} | 0x7072696D6172795F6B6579 | {"type": "object"} |
+-------------------------------------+--------------------------+--------------------+
1 row in set (0.0007 sec)

このようにtrueを指定すると、何も指定してないのと同じ結果になることがわかります。つまり全件削除したい場合、"true"と指定すれば良さそうに思えます。試してみましょう。

 MySQL  localhost  test  JS > table.remove("true")
Query OK, 1 item affected (0.0141 sec)
 MySQL  localhost  test  JS > table.find()
Empty set (0.0006 sec)

無事削除できていることがわかりました。

まとめ

今回は、MySQL ShellでJavaScriptで書いたコードでデータを取得書き込み削除する方法を紹介させていただきました。_id等少し気になる動作もありますが、基本的な操作はNoSQLを扱うように使用できることが紹介できたと思います。JSON型を扱うには、SQLよりもやはりJSONの方が使いやすい場面もあると思いますので、ぜひ活用してみましょう。

おすすめ記事

記事・ニュース一覧