バージョンに更新:ジャンゴ1.10とPostgresの9.6ジャンゴ/ PostgreSQLのjsonb(JSONField) - 選択変換し、1つのクエリ
私は、Pythonへのラウンドトリップなし代わりに、ネストされたJSONFieldのキーを変更しようとしています。理由は競合状態と複数の照会が同じフィールドを別の更新で上書きするのを避けることです。
オリジナルのフィールド値(デモのみ、実際のデータは、より複雑です):
私はDjangoは単一のクエリになるだろうが、それは2として記録されていますことをチェーンに希望のメソッドを試してみました
from exampleapp.models import AdhocTask
record = AdhocTask.objects.get(id=1)
print(record.log)
> {'demo_key': 'original'}
問合せ:
from django.db.models import F
from django.db.models.expressions import RawSQL
(AdhocTask.objects.filter(id=25)
.annotate(temp=RawSQL(
# `jsonb_set` gets current json value of `log` field,
# take a the nominated key ("demo key" in this example)
# and replaces the value with the json provided ("new value")
# Raw sql is wrapped in triple quotes to avoid escaping each quote
"""jsonb_set(log, '{"demo_key"}','"new value"', false)""",[]))
# Finally, get the temp field and overwrite the original JSONField
.update(log=F('temp’))
)
ケRY履歴(二つの別々のクエリなどを示して、この):
from django.db import connection
print(connection.queries)
> {'sql': 'SELECT "exampleapp_adhoctask"."id", "exampleapp_adhoctask"."description", "exampleapp_adhoctask"."log" FROM "exampleapp_adhoctask" WHERE "exampleapp_adhoctask"."id" = 1', 'time': '0.001'},
> {'sql': 'UPDATE "exampleapp_adhoctask" SET "log" = (jsonb_set(log, \'{"demo_key"}\',\'"new value"\', false)) WHERE "exampleapp_adhoctask"."id" = 1', 'time': '0.001'}]
、感謝マイケル:
jsonb_set
に関する詳細に興味を持って誰でもpostgresのドキュメント内の表9-45を見ている必要があります。私は 'Func'を継承した経験がありませんでした。実際にタイプヒントを見るのも良いです。コードの可読性と意図を理解することは間違いありません。 –