sql >> データベース >  >> RDS >> PostgreSQL

特定の要素のJSONB配列の更新

    PostgreSQL 11+

    すでにPostgreSQLv。11を使用している場合(新しいJSONB 型変換のサポート )最善の策は、おそらくPerlまたはPythonで記述されたカスタム関数でしょう。

    私はPython3を好むので、ここに機能的な例があります:

    CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
        RETURNS jsonb
        TRANSFORM FOR TYPE jsonb
        LANGUAGE plpython3u
    AS $$
    v_new = val
    tmp = v_new
    for e in path_to_array:
        tmp = tmp[e]
    
    for item in tmp:
        if (entry_filters is None or entry_filters.items() <= item.items()):
            item.update(replacement)
    
    return v_new
    $$;
    

    ...次のように使用できます:

    UPDATE configuration
    SET
      config = jsonb_replace_in_array(
        config,
        '{data}',
        '{"value":"changed"}'::jsonb,
        '{"oid":"11.5.15.1.4","instance":"1.1.4"}'::jsonb
      )
    WHERE config->'data' @> '[{"oid":"11.5.15.1.4","instance":"1.1.4"}]';
    

    そうです、条件は重複していますが、最初に触れる行の数を制限するためだけです。

    プレーンなPostgreSQL11インストールで実際に機能するには、拡張機能plpython3uが必要です。 およびjsonb_plpython3u

    CREATE EXTENSION plpython3u;
    CREATE EXTENSION jsonb_plpython3u;
    

    Pythonロジックの説明:

    for e in path_to_array:
        tmp = tmp[e]
    

    ...確認する必要のあるエントリの配列にたどり着きます。

    for item in tmp:
        if (entry_filters is None or entry_filters.items() <= item.items()):
            item.update(replacement)
    

    ...配列内の各アイテムについて、フィルター基準がnullであるかどうかを確認します (entry_filters is None =任意のエントリに一致)またはエントリがキーと値を含む提供された例を「含む」かどうか(entry_filters.items() <= item.items()

    enエントリが一致する場合は、提供された置換でコンテンツを上書き/追加します。

    それがあなたが探している方向に進むことを願っています。

    JSON変更に関連するPostgreSQLの現在の機能を見ると、非常に複雑であり(複雑ではないにしても)、純粋なSQLで同じことを行うには多くのオーバーヘッドが発生します。

    PostgreSQL9.6以降

    バージョン11がまだ利用できない場合、次の関数は型変換自体を処理することを犠牲にして同じことを行いますが、完全にAPI互換性を維持するため、アップグレードしたら、必要なことは1つだけです。関数を置き換えます(この関数を使用するステートメントを変更する必要はありません):

    CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
        RETURNS jsonb
        LANGUAGE plpython3u
    AS $$
    import json
    
    v_new = json.loads(val)
    t_replace = json.loads(replacement)
    t_filters = json.loads(entry_filters)
    tmp = v_new
    for e in path_to_array:
        tmp = tmp[e]
    
    for item in tmp:
        if (entry_filters is None or t_filters.items() <= item.items()):
            item.update(t_replace)
    
    return json.dumps(v_new)
    $$;
    



    1. ストアドプロシージャではデータのロードは許可されていません

    2. SQLドメインエラー:列が存在しません。デフォルトを設定しています

    3. 管理者の許可なしにPHPMyAdminを使用してmysqlのタイムゾーンを変更するにはどうすればよいですか?

    4. Mysqljsonベースのトレンドタグの実装