Dodock expose trois fonctions SQL spécialisées pour manipuler des champs contenant des données JSON : JSONValue, JSONExtract et JSONContains. Ces fonctions permettent d'extraire ou de filtrer des valeurs imbriquées dans un champ JSON directement depuis le Query Builder Python, sans avoir à charger l'ensemble des documents en mémoire.
JSON_VALUE, JSON_EXTRACT, JSON_CONTAINS). Elles nécessitent MariaDB 10.2.3 ou supérieur.from frappe.query_builder.functions import JSONValue, JSONExtract, JSONContains
JSONValue(champ, chemin) extrait une valeur scalaire (chaîne, nombre, booléen) depuis un champ JSON en suivant un chemin JSONPath.
JSONValue(champ, chemin_jsonpath)
| Paramètre | Type | Description |
|---|---|---|
champ | Colonne Dodock | Champ du DocType contenant la valeur JSON |
chemin_jsonpath | str | Expression JSONPath commençant par $ |
Soit un DocType Profile avec un champ preferences_json stockant :
{"notifications": {"email": true, "sms": false}, "language": "en"}
import frappe
from frappe.query_builder.functions import JSONValue
Profile = frappe.qb.DocType("Profile")
resultats = (
frappe.qb.from_(Profile)
.select(
Profile.customer_name,
JSONValue(Profile.preferences_json, "$.notifications.email").as_("notif_email"),
JSONValue(Profile.preferences_json, "$.language").as_("langue"),
)
.where(JSONValue(Profile.preferences_json, "$.notifications.email") == "true")
).run(as_dict=True)
Cette requête retourne uniquement les profils dont les notifications par e-mail sont activées, en exposant directement les valeurs extraites comme colonnes nommées.
JSONExtract(champ, chemin) extrait une valeur ou un fragment JSON (y compris un tableau ou un objet imbriqué) depuis un champ JSON. Contrairement à JSONValue, le résultat peut être un tableau JSON ou un objet, pas seulement une valeur scalaire.
JSONExtract(champ, chemin_jsonpath)
Soit un DocType Sales Order avec un champ applied_discounts_json stockant :
{"codes": ["WELCOME10", "FREESHIP", "VIP"]}
from frappe.query_builder.functions import JSONExtract
SalesOrder = frappe.qb.DocType("Sales Order")
codes = (
frappe.qb.from_(SalesOrder)
.select(
SalesOrder.name,
JSONExtract(SalesOrder.applied_discounts_json, "$.codes").as_("codes_remise"),
)
).run(as_dict=True)
Le résultat de JSONExtract sur un tableau est une chaîne JSON de type ["WELCOME10", "FREESHIP", "VIP"], que vous pouvez ensuite passer à JSONContains.
JSONContains(cible, valeur) vérifie si une valeur est contenue dans un document ou un tableau JSON. Elle est particulièrement utile pour filtrer des listes stockées en JSON.
JSONContains(cible, valeur)
| Paramètre | Type | Description |
|---|---|---|
cible | Colonne ou résultat de JSONExtract | Fragment JSON dans lequel chercher |
valeur | str | Valeur JSON à rechercher (encodée en chaîne) |
import frappe
from frappe.query_builder.functions import JSONContains, JSONExtract
SalesOrder = frappe.qb.DocType("Sales Order")
commandes = (
frappe.qb.from_(SalesOrder)
.select(SalesOrder.name, SalesOrder.customer)
.where(
JSONContains(
JSONExtract(SalesOrder.applied_discounts_json, "$.codes"),
'"FREESHIP"',
)
)
).run(as_dict=True)
'"FREESHIP"' et non 'FREESHIP'.Les trois fonctions sont composables. Voici un exemple réel combinant JSONExtract et JSONContains pour filtrer les commandes client ayant bénéficié de la livraison gratuite :
import frappe
from frappe.query_builder.functions import JSONContains, JSONExtract, JSONValue
SalesOrder = frappe.qb.DocType("Sales Order")
Profile = frappe.qb.DocType("Profile")
# Commandes avec livraison gratuite pour les clients ayant activé les notifications e-mail
resultats = (
frappe.qb.from_(SalesOrder)
.inner_join(Profile)
.on(SalesOrder.customer == Profile.name)
.select(SalesOrder.name, SalesOrder.customer, SalesOrder.grand_total)
.where(
JSONContains(
JSONExtract(SalesOrder.applied_discounts_json, "$.codes"),
'"FREESHIP"',
)
)
.where(JSONValue(Profile.preferences_json, "$.notifications.email") == "true")
).run(as_dict=True)
| Fonction | Équivalent SQL | Retourne | Cas d'usage typique |
|---|---|---|---|
JSONValue(champ, chemin) | JSON_VALUE() | Valeur scalaire | Lire $.language, $.price |
JSONExtract(champ, chemin) | JSON_EXTRACT() | Valeur ou fragment JSON | Extraire un tableau $.codes |
JSONContains(cible, valeur) | JSON_CONTAINS() | 0 ou 1 | Vérifier la présence dans un tableau |