web-dev-qa-db-fra.com

Sélectionnez, où JSON Array contient

Donc, dans Laravel 5, il y a la chose pratique appelée JSON Where Clauses utilisant la nouvelle capacité de MySQL pour stocker et récupérer JSON stocké dans une colonne:

User::where('meta->colors', 'red')->get()

retournerait toutes les lignes, où colors dans la colonne meta serait réglé sur red.

Supposons maintenant que colors n'est pas une chaîne, mais un tableau contenant plusieurs couleurs (colors => ['red', 'blue', 'green']).

Quel serait un moyen efficace de récupérer toutes les lignes, où colors contient par exemple la valeur red?

11
Elwin

JSON_CONTAINS() fait exactement ce que vous recherchez:

JSON_CONTAINS(target, candidate[, path])

Indique en retournant 1 ou 0 si un document JSON candidat donné est contenu dans un document JSON cible, ou - si un argument de chemin a été fourni - si le candidat se trouve à un chemin spécifique dans la cible. - 12.16.3 Fonctions qui recherchent les valeurs JSON

Actuellement, le générateur de requêtes de Laravel ne fournit pas d'API correspondante. Il y a cependant proposition interne ouverte .

En attendant, vous pouvez exécuter une requête brute:

\DB::table('users')->whereRaw(
    'JSON_CONTAINS(meta->"$.colors", \'["red"]\')'
)->get();

Ce qui retournerait tous les utilisateurs qui ont "rouge" dans leur champ JSON meta->colors. Notez que -> Opérateur nécessite MySQL 5.7.9+.

Vous pouvez également appeler la whereRaw() directement sur un modèle Eloquent.

Laravel 5.6

Depuis la version 5.6, le générateur de requêtes de Laravel contient une nouvelle méthode whereJsonContains .

16
sepehr

Je pense qu'une façon serait d'utiliser l'opérateur like:

User::where('meta->colors', 'like', '%"red"%')

Cependant, cela ne fonctionnerait que si les valeurs ne contiennent jamais le caractère " et les délimiteurs ne changeraient pas.

2
Elwin

Une mise à jour de cette réponse , selon MySQL ou MariaDb , la syntaxe correcte doit être JSON_CONTAINS(@json, 'red', '$.colors'), et est nécessaire pour utiliser JSON_EXTRACT.

Donc, eux, le code à l'intérieur Laravel (pour la version 5.5 ou moins).

Comme par exemple @ Elwin , la colonne meta doit contenir le JSON suivant: { "colors": ["red", "blue", "green"] }

User::whereRaw("JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '\"{$color}\"')")

N'oubliez pas d'utiliser des guillemets doubles dans la phrase de valeur.
JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '"red"')

0
alvaro.canepa