SQL Server용 JSONField

이 문서에서는 Django의 JSONFieldmssql-django 백엔드를 통해 SQL Server와 함께 작동하는 방식과 지원되는 조회 기능 및 제한 사항을 설명합니다.

사전 요구 사항

  • SQL Server 2016 이상(JSON 함수 필요)
  • mssql-django 1.2 이상

JSONField가 SQL Server 매핑하는 방법

Django의 JSONField는 SQL Server에서 JSON CHECK 제약 조건이 있는 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()

contains

메모

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()

메모

mssql-django 백엔드에서는 키가 존재하지만 그 값이 JSON null인 경우 has_key는 빈 QuerySet을 반환합니다. 이는 PostgreSQL과는 다릅니다. PostgreSQL에서는 값에 관계없이 has_keyTrue를 반환합니다. 조회는 isnull=True 키가 없는 개체와 값 null이 있는 개체를 반환합니다.

값이 '없음'일 때 정확히 일치

exact 조회는 None 값을 지원하지 않습니다. 다음 쿼리는 빈 QuerySet을 반환합니다.

# Returns empty QuerySet - use isnull lookup instead
Item.objects.filter(metadata__color=None).values()

대신 isnull 조회를 사용하여 null 값을 찾으세요.

Limitations

  • JSONField를 사용한 대량 업데이트: JSONField 값과 함께 bulk_update를 사용할 때, 특히 Django 5.2 이상 버전에서는 몇 가지 예외적인 경우가 있습니다. 자세한 내용은 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 문자열 값의 리터럴 따옴표 문자: 리터럴 " 문자가 포함된 JSON 문자열 값에 대한 동등성 조회는 저장된 행과 일치하지 않을 수 있습니다(예: metadata={"description": '"quoted"'}). 따옴표 문자가 포함된 값은 올바르게 저장되지만 필드 조회를 통해 안정적으로 검색할 수 없습니다.