Draft.jsとは、Facebook(現在Meta社)が開発しているReactにリッチエディタを簡単に導入できるライブラリです。
Draft.jsはエディタに入力された文字のスタイル(太字など)も管理するため、テキストを入力するとDraft.jsではスタイルを含んだJsonを返します。
例えば、単に テスト投稿です
とエディタに入力すると以下のようなJsonが生成されます。
{
"blocks": [
{
"key": "4s107",
"data": {
},
"text": "テスト投稿です",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
}
],
"entity_map": {
}
}
この記事では、上記のようなJsonデータからテキスト部分に対して、あいまい検索するためのクエリが、普段Jsonをそれほど使わない私には、難しく、記事もなかなかで出てこなかったので、今回記事にしました。
なお、今回はJson型ではなく、JSONB型を扱っています。DBはPostgreSQLを利用しています。
あいまい検索するSQL
今回、contentというカラムがjsonb型になっており、そのカラムに以下のデータが入っています。
{
"blocks": [
{
"key": "4s107",
"data": {
},
"text": "テスト投稿です",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
}
],
"entity_map": {
}
}
SQLはこちらです。
SELECT id, content
FROM posts, JSONB_ARRAY_ELEMENTS(content->'blocks') AS block
WHERE block ->> 'text' LIKE '%投稿%'
以下補足
JSONB_ARRAY_ELEMENTSとは何かというと、、、
JSONB_ARRAY_ELEMENTSの参考:https://www.postgresql.jp/document/13/html/functions-json.html
たとえば、こんなJSONがあり、このblocksの配列を返したいときに
JSONの例
{
"blocks": [
{
"key": "bk52m",
"data": {
},
"text": "yahoo",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
},
{
"key": "514td",
"data": {
},
"text": "google",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
},
{
"key": "7kqtk",
"data": {
},
"text": "edge",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
},
{
"key": "a1hj2",
"data": {
},
"text": "safari",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
},
{
"key": "ehcpf",
"data": {
},
"text": "https://example.com",
"type": "unstyled",
"depth": 0,
"entity_ranges": [
],
"inline_style_ranges": [
]
}
],
"entity_map": {
}
}
SELECT id, JSONB_ARRAY_ELEMENTS(content->'blocks') as blocks
FROM posts;
上記のSQLでblocksの配列が返ってきます
# SELECT id, JSONB_ARRAY_ELEMENTS(content->'blocks') as blocks
FROM posts;
id | blocks
--------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------
beda9f03-3131-4845-b43a-a422ce82a59d | {"key": "4s107", "data": {}, "text": "テスト投稿です", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
42733b11-b091-4d05-886a-af9fb942eb5b | {"key": "bk52m", "data": {}, "text": "yahoo", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
42733b11-b091-4d05-886a-af9fb942eb5b | {"key": "514td", "data": {}, "text": "google", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
42733b11-b091-4d05-886a-af9fb942eb5b | {"key": "7kqtk", "data": {}, "text": "edge", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
42733b11-b091-4d05-886a-af9fb942eb5b | {"key": "a1hj2", "data": {}, "text": "safari", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
42733b11-b091-4d05-886a-af9fb942eb5b | {"key": "ehcpf", "data": {}, "text": "https://example.com", "type": "unstyled", "depth": 0, "entity_ranges": [], "inline_style_ranges": []}
(6 rows)
なので、上記のblocksのうち、さらにtext部分を抽出するには、、、
=# SELECT id, JSONB_ARRAY_ELEMENTS(content->'blocks') ->> 'text' as text
FROM posts;
id | text
--------------------------------------+---------------------
beda9f03-3131-4845-b43a-a422ce82a59d | テスト投稿です
42733b11-b091-4d05-886a-af9fb942eb5b | yahoo
42733b11-b091-4d05-886a-af9fb942eb5b | google
42733b11-b091-4d05-886a-af9fb942eb5b | edge
42733b11-b091-4d05-886a-af9fb942eb5b | safari
42733b11-b091-4d05-886a-af9fb942eb5b | https://example.com
(6 rows)
上記のようなSQLでtext部分の抽出ができます。