JSONField met SQL Server

In dit artikel wordt uitgelegd hoe Django JSONField met SQL Server werkt via de mssql-django back-end, inclusief ondersteunde zoekacties en beperkingen.

Prerequisites

  • SQL Server 2016 of hoger (JSON-functies zijn vereist)
  • mssql-django 1.2 of hoger

Hoe JSONField wordt vertaald naar SQL Server

Django's JSONField wordt toegewezen aan nvarchar(max) met een JSON-checkbeperking in SQL Server. De back-end maakt gebruik van de ingebouwde JSON-functies van SQL Server (JSON_VALUE, JSON_QUERY, ISJSON) om zoekacties en query's te implementeren.

Een model definiƫren met JSONField

Voeg het volgende model toe aan myapp/models.py. In de voorbeelden in dit artikel wordt een Item model gebruikt, zodat ze niet conflicteren met het Product model uit de Django-quickstart.

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)

Genereer en pas de migratie toe zodat de onderliggende tabel in SQL Server bestaat:

python manage.py makemigrations myapp
python manage.py migrate myapp

JSON-gegevens opslaan en ophalen

Open de Django-shell met python manage.py shell. Importeer het model bij de >>> prompt:

from myapp.models import Item

Maak een record met JSON-gegevens:

item = Item.objects.create(
    name="Widget",
    metadata={"color": "blue", "weight": 1.5, "dimensions": {"height": 10, "width": 5}},
    tags=["sale", "new"],
)

Haal de record op en krijg toegang tot JSON-waarden:

item = Item.objects.get(name="Widget")
print(item.metadata["color"])  # "blue"
print(item.tags)  # ["sale", "new"]

Ondersteunde zoekacties

De mssql-django back-end ondersteunt de volgende JSONField-zoekacties:

Sleutel-/indexzoekacties

Geneste JSON-waarden openen met behulp van de dubbele onderstrepingstekensyntaxis van Django:

# Filter by nested key value
Item.objects.filter(metadata__color="blue").values()

# Access nested objects
Item.objects.filter(metadata__dimensions__height=10).values()

bevat

Note

De contains opzoeking wordt niet ondersteund door de mssql-django backend. Gebruik has_key met key-path-lookups als alternatief:

# Instead of: Item.objects.filter(metadata__contains={"color": "blue"})
# Use key-path lookup:
Item.objects.filter(metadata__color="blue").values()

has_key

Controleer of er een specifieke sleutel bestaat:

Item.objects.filter(metadata__has_key="color").values()

has_keys

Controleer of alle opgegeven sleutels bestaan:

Item.objects.filter(metadata__has_keys=["color", "weight"]).values()

has_any_keys

Controleer of er een van de opgegeven sleutels bestaat:

Item.objects.filter(metadata__has_any_keys=["color", "size"]).values()

isnull

De isnull zoekactie heeft specifiek gedrag met 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

Op de mssql-django-backend retourneert has_key, als een sleutel bestaat maar een JSON-waarde null heeft, een lege QuerySet. Dit verschilt van PostgreSQL, waarbij has_key retourneert True ongeacht de waarde. De isnull=True zoekactie retourneert objecten waar de sleutel niet bestaat en objecten waar de waarde zich bevindt null.

exact met Geen

De exact zoekactie biedt geen ondersteuning voor None waarden. De volgende query retourneert een lege QuerySet:

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

Gebruik in plaats daarvan de isnull zoekactie om null-waarden te zoeken.

Limitations

  • Bulk-updates met JSONField: Er doen zich enkele uitzonderingssituaties voor bij het gebruik van bulk_update met JSONField-waarden, met name in Django 5.2 en latere versies. Zie Beperkingen en niet-ondersteunde functies in mssql-django voor meer informatie.
  • CASE WHEN-expressies: Op Django 5.2 en latere versies kunnen bepaalde JSONField-bewerkingen in CASE WHEN-expressies onverwachte resultaten opleveren.
  • exact met None: Gebruik isnull in plaats van exact te filteren op null JSON-waarden.
  • has_key met null-waarden: has_key retourneert een lege QuerySet voor sleutels die bestaan, maar een null waarde hebben.
  • Letterlijke aanhalingstekens in JSON-tekenreekswaarden: Gelijkheidszoekacties op JSON-tekenreekswaarden die letterlijke " tekens (bijvoorbeeld) bevatten, metadata={"description": '"quoted"'}komen mogelijk niet overeen met de opgeslagen rij. Waarden met aanhalingstekens worden correct opgeslagen, maar kunnen niet betrouwbaar worden opgehaald via veldzoekacties.