web-dev-qa-db-ja.com

JSON Postgresデータ型列で特定の文字列を検索するにはどうすればよいですか?

JSONを含むparamsという名前のテーブルにreportsという名前の列があります。

JSON配列のどこかにテキスト「authVar」を含む行を見つける必要があります。テキストが表示されるパスまたはレベルがわかりません。

標準のlike演算子でJSONを検索するだけです。

何かのようなもの:

SELECT * FROM reports
WHERE params LIKE '%authVar%'

Postgresのドキュメントを検索してグーグルで読みました。 JSONデータ型をよく理解していないので、簡単なものがないようです。

JSONは次のようになります。

[  
   {  
      "tileId":18811,
      "Params":{  
         "data":[  
            {  
               "name":"Week Ending",
               "color":"#27B5E1",
               "report":"report1",
               "locations":{  
                  "c1":0,
                  "c2":0,
                  "r1":"authVar",
                  "r2":66
               }
            }
         ]
      }
   }
]
14
Joshua Dance

不明なjson構造を再帰的に処理することは可能ですが、かなり複雑でコストがかかります。私はうまくいくブルートフォース法を提案します:

select *
from reports
where params::text like '%authVar%';
-- or 
-- where params::text like '%"authVar"%';
-- if you are looking for the exact value

クエリは非常に高速ですが、検索された文字列がいずれかのキーの一部である場合、予期しない余分な行が返されることがあります。

Postgres 12では、JSONBの再帰検索はjsonpathの新機能でかなり快適です。

authVarを含む文字列値を検索します。

select *
from reports
where jsonb_path_exists(params, '$.** ? (@.type() == "string" && @ like_regex "authVar")')

Jsonpath:

$.**                     find any value at any level (recursive processing)
?                        where
@.type() == "string"     value is string
&&                       and
@ like_regex "authVar"   value contains 'authVar'

または正確な値を見つけます:

select *
from reports
where jsonb_path_exists(params, '$.** ? (@ == "authVar")')

ドキュメントを読んでください:

25
klin