2016-02-04 36 views
9

I型jsontagsカラムを作りたい:MySQL:可変長のインデックスjson配列?

例えば、

id | tags 
========================================= 
1 | '["tag1", "tag2", "tag3"]' 
2 | '["tag1", "tag3", "tag5", "tag7"]' 
3 | '["tag2", "tag5"]' 

Iが配列(可変長)の長さを知らなくても、インデックスにアレイ内の各tagしたいです。

私はtag2を含む行を問い合わせるのであれば、その後、それが行1を返す必要があり、3

https://dev.mysql.com/doc/refman/5.7/en/json.html

JSON列に索引を付けることはできません。あなたは「スカラー値を抽出」により、JSON欄

からスカラー 値を抽出し、生成された列にインデックスを作成することでこの制限 を回避することができ、この平均は私がで&インデックスに各項目を抽出する必要がありますん配列は個別に(配列の最大長をすべて知っていなければならないという意味です)可変長配列のインデックスを作成するにはどうすればよいですか?

+0

いや、スカラーは、単純な値(対複雑なデータ構造)です。 –

+1

mysqlのデータを使って何かをしたいのであれば、それをjsonとして保存しないでください。正規化されたデータとして保存し、必要に応じてjsonとして吐き出します。 – Strawberry

+0

ストロベリーのコメントは重要な点を強調しています。例えば、 '' ["tag2"、 "tag5"] ''と' ["tag5"、 "tag2"]' 'は同じデータですか? –

答えて

0

「スカラー値を抽出する」とは、配列内の各項目を個別にインデックス化することを意味しますか?つまり、... &

必要な数だけ項目を抽出できます。これらは複合値(JSON)ではなく、スカラー(文字列など)として格納されます。

CREATE TABLE mytags (
    id INT NOT NULL AUTO_INCREMENT, 
    tags JSON, 
    PRIMARY KEY (id) 
); 

INSERT INTO mytags (tags) VALUES 
    ('["tag1", "tag2", "tag3"]'), 
    ('["tag1", "tag3", "tag5", "tag7"]'), 
    ('["tag2", "tag5"]'); 

SELECT * FROM mytags; 

+----+----------------------------------+ 
| id | tags        | 
+----+----------------------------------+ 
| 1 | ["tag1", "tag2", "tag3"]   | 
| 2 | ["tag1", "tag3", "tag5", "tag7"] | 
| 3 | ["tag2", "tag5"]     | 
+----+----------------------------------+ 

のは一つだけのアイテム(JSONオブジェクトから最初の値)でインデックスを作成してみましょう:

ALTER TABLE mytags 
    ADD COLUMN tags_scalar VARCHAR(255) GENERATED ALWAYS AS (json_extract(tags, '$[0]')), 
    ADD INDEX tags_index (tags_scalar); 

SELECT * FROM mytags; 

+----+----------------------------------+-------------+ 
| id | tags        | tags_scalar | 
+----+----------------------------------+-------------+ 
| 1 | ["tag1", "tag2", "tag3"]   | "tag1"  | 
| 2 | ["tag1", "tag3", "tag5", "tag7"] | "tag1"  | 
| 3 | ["tag2", "tag5"]     | "tag2"  | 
+----+----------------------------------+-------------+ 

今、あなたはVARCHAR列tags_scalarにインデックスを持っています。値もスキップすることができ、引用符、含まれています

ALTER TABLE `testy`.`mytags` 
    DROP COLUMN `tags_scalar`, 
    DROP INDEX `tags_index`; 

ALTER TABLE mytags 
    ADD COLUMN tags_scalar VARCHAR(255) GENERATED ALWAYS AS (json_extract(tags, '$[0]', '$[1]', '$[2]')), 
    ADD INDEX tags_index (tags_scalar); 

SELECT * from mytags; 

+----+----------------------------------+--------------------------+ 
| id | tags        | tags_scalar    | 
+----+----------------------------------+--------------------------+ 
| 1 | ["tag1", "tag2", "tag3"]   | ["tag1", "tag2", "tag3"] | 
| 2 | ["tag1", "tag3", "tag5", "tag7"] | ["tag1", "tag3", "tag5"] | 
| 3 | ["tag2", "tag5"]     | ["tag2", "tag5"]   | 
+----+----------------------------------+--------------------------+ 

または自動生成するany other valid expressionを使用します。

ALTER TABLE `testy`.`mytags` 
    DROP COLUMN `tags_scalar`, 
    DROP INDEX `tags_index`; 

ALTER TABLE mytags 
    ADD COLUMN tags_scalar VARCHAR(255) GENERATED ALWAYS AS (json_unquote(json_extract(tags, '$[0]'))), 
    ADD INDEX tags_index (tags_scalar); 

SELECT * FROM mytags; 

+----+----------------------------------+-------------+ 
| id | tags        | tags_scalar | 
+----+----------------------------------+-------------+ 
| 1 | ["tag1", "tag2", "tag3"]   | tag1  | 
| 2 | ["tag1", "tag3", "tag5", "tag7"] | tag1  | 
| 3 | ["tag2", "tag5"]     | tag2  | 
+----+----------------------------------+-------------+ 

すでに想像できるように、生成された列はJSONから複数の項目を含めることができます"tag1tag3tag5tag7"のように簡単に索引付けして検索できるものを取得するために、JSON構造体から文字列を削除します。

[...](すべてインデックスにするには配列の最大長を知っている必要があります)

。上述のように、あなたが知っている必要はありません - NULL値は、任意の有効な式を使用してスキップすることができます。もちろん、それは常に知っている方が良いです。
ここでアーキテクチャの決定があります:JSONデータ型が目標を達成するのに最も適切ですか?この特定の問題を解決するには? JSONは正しいツールですか?それは検索をスピードアップするつもりですか?

可変長配列のインデックスを作成するにはどうすればよいですか?

あなたは、キャスト文字列を主張する場合:

ALTER TABLE `testy`.`mytags` 
    DROP COLUMN `tags_scalar`, 
    DROP INDEX `tags_index`; 

ALTER TABLE mytags 
    ADD COLUMN tags_scalar VARCHAR(255) GENERATED ALWAYS AS (replace(replace(replace(cast(tags as char), '"', ''), '[', ''), ']', '')), 
    ADD INDEX tags_index (tags_scalar); 
SELECT * from mytags; 

+----+----------------------------------+------------------------+ 
| id | tags        | tags_scalar   | 
+----+----------------------------------+------------------------+ 
| 1 | ["tag1", "tag2", "tag3"]   | tag1, tag2, tag3  | 
| 2 | ["tag1", "tag3", "tag5", "tag7"] | tag1, tag3, tag5, tag7 | 
| 3 | ["tag2", "tag5"]     | tag2, tag5    | 
+----+----------------------------------+------------------------+ 

この方法か、あなたが最も適し索引構造(some options)を適用VARCHARまたはTEXTの列、で終わる別。

さらに読書: