Jointures réflexives Azure Cosmos DB for NoSQL
S’APPLIQUE À : NoSQL
Dans Azure Cosmos DB for NoSQL, les données sont sans schéma et généralement dénormalisées. Au lieu de joindre des données entre des entités et des ensembles, comme vous le feriez dans une base de données relationnelle, les jointures se produisent au sein d’un seul article. Plus précisément, les jointures se délimitent à cet article et ne peuvent pas se produire sur plusieurs articles et conteneurs.
Conseil
Si vous avez besoin de joindre des articles et des conteneurs, envisagez de retravailler votre modèle de données pour éviter cette situation.
Jointure réflexive avec un seul article
Examinons un exemple de jointure réflexive au sein d’un article. Considérez un conteneur avec un seul article. Cet article représente un produit avec différentes étiquettes :
[
{
"id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
"categoryId": "bbbbbbbb-1111-2222-3333-cccccccccccc",
"name": "Teapo Surfboard (6'10\") Grape",
"sku": "teapo-surfboard-72109",
"tags": [
{
"id": "cccccccc-2222-3333-4444-dddddddddddd",
"slug": "tail-shape-swallow",
"name": "Tail Shape: Swallow"
},
{
"id": "dddddddd-3333-4444-5555-eeeeeeeeeeee",
"slug": "length-inches-82",
"name": "Length: 82 inches"
},
{
"id": "eeeeeeee-4444-5555-6666-ffffffffffff",
"slug": "color-group-purple",
"name": "Color Group: Purple"
}
]
}
]
Que se passe-t-il si vous avez besoin de trouver le groupe de couleurs de ce produit ? En règle générale, vous avez besoin d’écrire une requête qui a un filtre qui vérifie chaque index potentiel dans le tableau tags
pour trouver une valeur avec un préfixe color-group-
.
SELECT
*
FROM
products p
WHERE
STARTSWITH(p.tags[0].slug, "color-group-") OR
STARTSWITH(p.tags[1].slug, "color-group-") OR
STARTSWITH(p.tags[2].slug, "color-group-")
Cette technique peut rapidement devenir intenable. La complexité ou la longueur de la syntaxe de requête augmente le nombre potentiel d’articles dans le tableau. De plus, cette requête n’est pas suffisamment flexible pour gérer les produits futurs, qui peuvent avoir plus de trois étiquettes.
Dans une base de données relationnelle traditionnelle, les étiquettes sont séparées dans une table distincte et une jointure entre tables est effectuée avec un filtre appliqué aux résultats. Dans l’API pour NoSQL, nous pouvons effectuer une opération de jointure réflexive au sein de l’article à l’aide du mot clé JOIN
.
SELECT
p.id,
p.sku,
t.slug
FROM
products p
JOIN
t IN p.tags
Cette requête retourne un tableau simple avec un article pour chaque valeur incluse dans le tableau des étiquettes.
[
{
"id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
"sku": "teapo-surfboard-72109",
"slug": "tail-shape-swallow"
},
{
"id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
"sku": "teapo-surfboard-72109",
"slug": "length-inches-82"
},
{
"id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
"sku": "teapo-surfboard-72109",
"slug": "color-group-purple"
}
]
Décomposons la requête. La requête a désormais deux alias : p
pour chaque article dans le jeu de résultats et t
pour le tableau tags
à jointure réflexive. Le mot clé *
est valide uniquement pour projeter tous les champs s’il peut déduire le jeu de données d’entrée, mais il existe maintenant deux jeux de données d’entrée (p
et t
). En raison de cette contrainte, nous devons définir explicitement nos champs retournés en tant que id
et sku
à partir du produit, ainsi que slug
à partir des étiquettes. Pour faciliter la lecture et la compréhension de cette requête, nous pouvons supprimer le champ id
et utiliser un alias pour le champ name
de l’étiquette afin de le renommer tag
.
SELECT
p.sku,
t.name AS tag
FROM
products p
JOIN
t IN p.tags
[
{
"sku": "teapo-surfboard-72109",
"tag": "Tail Shape: Swallow"
},
{
"sku": "teapo-surfboard-72109",
"tag": "Length: 82 inches"
},
{
"sku": "teapo-surfboard-72109",
"tag": "Color Group: Purple"
}
]
Enfin, nous pouvons utiliser un filtre pour rechercher l’étiquette color-group-purple
. Étant donné que nous avons utilisé le mot clé JOIN
, notre filtre est suffisamment flexible pour gérer n’importe quel nombre variable d’étiquettes.
SELECT
p.sku,
t.name AS tag
FROM
products p
JOIN
t IN p.tags
WHERE
STARTSWITH(t.slug, "color-group-")
[
{
"sku": "teapo-surfboard-72109",
"tag": "Color Group: Purple"
}
]
Jointure réflexive de plusieurs articles
Passons à un exemple où nous devons trouver une valeur, au sein d’un tableau, qui existe dans plusieurs articles. Pour cet exemple, considérez un conteneur avec deux articles. Chaque article contient les étiquettes pertinentes qui le concernent.
[
{
"id": "ffffffff-5555-6666-7777-aaaaaaaaaaaa",
"categoryId": "cccccccc-8888-9999-0000-dddddddddddd",
"categoryName": "Sleeping Bags",
"name": "Maresse Sleeping Bag (6') Ming",
"sku": "maresse-sleeping-bag-65503",
"tags": [
{
"id": "b1b1b1b1-cccc-dddd-eeee-f2f2f2f2f2f2",
"slug": "bag-shape-mummy",
"name": "Bag Shape: Mummy"
},
{
"id": "bbbbbbbb-7777-8888-9999-cccccccccccc",
"slug": "bag-insulation-down-fill",
"name": "Bag Insulation: Down Fill"
}
]
},
{
"id": "c2c2c2c2-dddd-eeee-ffff-a3a3a3a3a3a3",
"categoryId": "cccccccc-8888-9999-0000-dddddddddddd",
"categoryName": "Sleeping Bags",
"name": "Vareno Sleeping Bag (6') Turmeric",
"sku": "vareno-sleeping-bag-65508",
"tags": [
{
"id": "dddddddd-9999-0000-1111-eeeeeeeeeeee",
"slug": "bag-insulation-synthetic-fill",
"name": "Bag Insulation: Synthetic Fill"
},
{
"id": "a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
"slug": "color-group-yellow",
"name": "Color Group: Yellow"
},
{
"id": "b1b1b1b1-cccc-dddd-eeee-f2f2f2f2f2f2",
"slug": "bag-shape-mummy",
"name": "Bag Shape: Mummy"
}
]
}
]
Que se passe-t-il si vous avez besoin de trouver chaque article dont la forme est celle d’un sac à langer ? Vous pouvez rechercher l’étiquette bag-shape-mummy
, mais vous avez besoin d’écrire une requête complexe qui tient compte des deux caractéristiques de ces articles :
L’étiquette avec un préfixe
bag-shape-
se produit à différents index dans chaque tableau. Pour le sac de couchage Vareno, l’étiquette correspond au troisième article (index :2
). Pour le sac de couchage Maresse, l’étiquette correspond au premier article (index :0
).Le tableau
tags
de chaque article est d’une longueur différente. Le sac de couchage Vareno a deux étiquettes tandis que le sac de couchage Maresse en a trois.
Ici, le mot clé JOIN
est un excellent outil pour créer un produit croisé des articles et étiquettes. Les jointures créent un produit croisé complet des ensembles participant à la jointure. Le résultat est un ensemble de tuples avec chaque permutation de l’article et des valeurs au sein du tableau ciblé.
Une opération de jointure sur nos exemples de produits et étiquettes de sac de couchage va créer les articles suivants :
Élément | Tag |
---|---|
Sac de couchage Maresse (6’) Ming | Forme de sac : Sac à langer |
Sac de couchage Maresse (6’) Ming | Isolant du sac : Garnissage en duvet |
Sac de couchage Vareno (6’) Turmeric | Isolant du sac : Garnissage synthétique |
Sac de couchage Vareno (6’) Turmeric | Groupe de couleurs : Jaune |
Sac de couchage Vareno (6’) Turmeric | Forme de sac : Sac à langer |
Voici la requête SQL et le jeu de résultats JSON pour une jointure qui inclut plusieurs articles dans le conteneur.
SELECT
p.sku,
t.name AS tag
FROM
products p
JOIN
t IN p.tags
WHERE
p.categoryName = "Sleeping Bags"
[
{
"sku": "maresse-sleeping-bag-65503",
"tag": "Bag Shape: Mummy"
},
{
"sku": "maresse-sleeping-bag-65503",
"tag": "Bag Insulation: Down Fill"
},
{
"sku": "vareno-sleeping-bag-65508",
"tag": "Bag Insulation: Synthetic Fill"
},
{
"sku": "vareno-sleeping-bag-65508",
"tag": "Color Group: Yellow"
},
{
"sku": "vareno-sleeping-bag-65508",
"tag": "Bag Shape: Mummy"
}
]
Tout comme pour l’article unique, vous pouvez appliquer un filtre ici pour rechercher uniquement les articles qui correspondent à une étiquette spécifique. Par exemple, cette requête recherche tous les articles avec une étiquette nommée bag-shape-mummy
pour répondre à l’exigence initiale mentionnée plus haut dans cette section.
SELECT
p.sku,
t.name AS tag
FROM
products p
JOIN
t IN p.tags
WHERE
p.categoryName = "Sleeping Bags" AND
t.slug = "bag-shape-mummy"
[
{
"sku": "maresse-sleeping-bag-65503",
"tag": "Bag Shape: Mummy"
},
{
"sku": "vareno-sleeping-bag-65508",
"tag": "Bag Shape: Mummy"
}
]
Vous pouvez également modifier le filtre pour obtenir un autre jeu de résultats. Par exemple, cette requête recherche tous les articles qui ont une étiquette nommée bag-insulation-synthetic-fill
.
SELECT
p.sku,
t.name AS tag
FROM
products p
JOIN
t IN p.tags
WHERE
p.categoryName = "Sleeping Bags" AND
t.slug = "bag-insulation-synthetic-fill"
[
{
"sku": "vareno-sleeping-bag-65508",
"tag": "Bag Insulation: Synthetic Fill"
}
]