この記事では、サポートされている参照と制限事項など、Django のJSONFieldがmssql-django バックエンドを介してSQL Serverと連携する方法について説明します。
Prerequisites
- SQL Server 2016 以降 (JSON 関数が必要)
-
mssql-django1.2 以降
JSONField をSQL Serverにマップする方法
Django のJSONFieldは、SQL Serverの JSON チェック制約を使用して nvarchar(max) にマップされます。 バックエンドは、SQL Serverの組み込みの JSON 関数 (JSON_VALUE、JSON_QUERY、ISJSON) を使用して、ルックアップとクエリを実装します。
JSONField を使用してモデルを定義する
次のモデルを myapp/models.pyに追加します。 この記事の例では、ItemのProduct モデルと競合しないように、 モデルを使用します。
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=100)
metadata = models.JSONField(default=dict)
tags = models.JSONField(null=True, blank=True)
基になるテーブルがSQL Serverに存在するように、移行を生成して適用します。
python manage.py makemigrations myapp
python manage.py migrate myapp
JSON データの格納と取得
python manage.py shellで Django シェルを開きます。
>>> プロンプトで、モデルをインポートします。
from myapp.models import Item
JSON データを含むレコードを作成します。
item = Item.objects.create(
name="Widget",
metadata={"color": "blue", "weight": 1.5, "dimensions": {"height": 10, "width": 5}},
tags=["sale", "new"],
)
レコードを取得し、JSON 値にアクセスします。
item = Item.objects.get(name="Widget")
print(item.metadata["color"]) # "blue"
print(item.tags) # ["sale", "new"]
サポートされている参照
mssql-django バックエンドでは、次の JSONField 参照がサポートされています。
キー/インデックスの参照
Django の二重アンダースコア構文を使用して、入れ子になった JSON 値にアクセスします。
# Filter by nested key value
Item.objects.filter(metadata__color="blue").values()
# Access nested objects
Item.objects.filter(metadata__dimensions__height=10).values()
含む
Note
contains バックエンドでは、mssql-django参照はサポートされていません。 別の方法として、キー パス参照で has_key を使用します。
# Instead of: Item.objects.filter(metadata__contains={"color": "blue"})
# Use key-path lookup:
Item.objects.filter(metadata__color="blue").values()
has_key
特定のキーが存在するかどうかを確認します。
Item.objects.filter(metadata__has_key="color").values()
has_keys
指定されたすべてのキーが存在するかどうかを確認します。
Item.objects.filter(metadata__has_keys=["color", "weight"]).values()
has_any_keys
指定したキーのいずれかが存在するかどうかを確認します。
Item.objects.filter(metadata__has_any_keys=["color", "size"]).values()
isnull
isnull参照には、SQL Serverを使用した特定の動作があります。
# Returns objects where the key doesn't exist AND keys with None value
Item.objects.filter(metadata__color__isnull=True).values()
# Returns objects where the key exists and has a non-null value
Item.objects.filter(metadata__color__isnull=False).values()
Note
mssql-django バックエンドで、キーが存在するが JSON null値を持つ場合、has_keyは空の QuerySet を返します。 これは PostgreSQL とは異なり、 has_key は値に関係なく True を返します。
isnull=True参照は、キーが存在しないオブジェクトと、値がnullオブジェクトを返します。
None を指定した場合と完全に一致する
exact参照では、None値はサポートされていません。 次のクエリでは、空の QuerySet が返されます。
# Returns empty QuerySet - use isnull lookup instead
Item.objects.filter(metadata__color=None).values()
代わりに、 isnull 参照を使用して null 値を検索します。
Limitations
-
JSONField を使用した一括更新: 特に Django 5.2 以降のバージョンで、JSONField 値で
bulk_updateを使用する場合にエッジ ケースが存在する場合があります。 詳細については、「 mssql-django の制限事項とサポートされていない機能」を参照してください。 - CASE WHEN 式: Django 5.2 以降のバージョンでは、CASE WHEN 式内の特定の JSONField 操作によって予期しない結果が発生する可能性があります。
-
exact with None: null の JSON 値をフィルタリングするには、
exactの代わりにisnullを使用します。 -
null 値を持つhas_key:
has_keyは、存在するがnull値を持つキーに対して空の QuerySet を返します。 -
JSON 文字列値のリテラル引用符文字: リテラル
"文字 (たとえば、metadata={"description": '"quoted"'}) を含む JSON 文字列値の等価参照が、格納されている行と一致しない可能性があります。 引用符文字を含む値は正しく格納されますが、フィールド参照では確実に取得できません。