Ma table / modèle a une colonne de type TEXT, et lors du filtrage des enregistrements sur le modèle lui-même, l'AR where produit le SQL correct et renvoie des résultats corrects, voici ce que je veux dire:

MyNamespace::MyValue.where(value: 'Good Quality')

Produit ce SQL:

SELECT `my_namespace_my_values`.* 
FROM `my_namespace_my_values` 
WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

Prenons un autre exemple où je rejoins MyNamespace::MyValue et filtre sur la même colonne value mais à partir de l'autre modèle (a une relation sur le modèle avec my_values). Voir ceci ( requête n ° 2 ):

OtherModel.joins(:my_values).where(my_values: { value: 'Good Quality' })

Cela ne produit pas une requête correcte, cela filtre sur la colonne value comme s'il s'agissait d'une colonne String et non de texte, produisant donc des résultats incorrects comme celui-ci (coller uniquement là où):

WHERE my_namespace_my_values`.`value` = 'Good Quality'

Maintenant, je peux surmonter cela en faisant LIKE dans mon AR where, ce qui produira le résultat correct mais une requête légèrement différente. Voici ce que je veux dire:

OtherModel.joins(:my_values).where('my_values.value LIKE ?, '%Good Quality%')

Arrivant enfin à mes questions. Qu'est-ce que c'est et comment est-il généré pour où sur le modèle (pour le type de colonne de texte)?

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

Peut-être la question la plus importante quelle est la différence en termes de performances en utilisant :

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

Et ça :

(my_namespace_my_values.value LIKE '%Good Quality%')

Et plus important encore, comment puis-je obtenir ma requête avec des jointures (requête n ° 2) produire où comme ceci :

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'
16
ant 23 mai 2018 à 01:58

3 réponses

Qu'est-ce que c'est et comment est-il généré pour où sur le modèle (pour le type de colonne de texte)?

C'est généré derrière le moteur lexical Active Records (Arel). Voir ma réponse ci-dessous sur votre deuxième question pour savoir pourquoi.

Quelle est la différence en termes de performances en utilisant ...

Le "=" correspond par comparaison chaîne / bloc entier Alors que LIKE correspond par caractère (s) (par caractère (s)).

Dans mes projets, j'ai des tables avec des millions de lignes, de mon expérience, c'est vraiment plus rapide à utiliser ce comparateur "=" ou expression régulière que d'utiliser un LIKE dans une requête.

Comment obtenir ma requête avec des jointures (requête n ° 2) produire où comme ceci ...

Pouvez-vous essayer cela,

OtherModel.joins(:my_values).where(OtherModel[:value].eq('\\\"Good Quality\\\"'))
2
Truth 25 mai 2018 à 14:03

Je pense que cela pourrait être utile.

pour rechercher \ n, spécifiez-le comme \ n. Pour rechercher \, spécifiez-le comme \\ c'est parce que les barres obliques inverses sont supprimées une fois par l'analyseur et à nouveau lorsque la correspondance de modèle est effectuée, laissant une seule barre oblique inverse à comparer.

lien

LIKE et = sont des opérateurs différents.

= est un opérateur de comparaison qui opère sur les nombres et les chaînes. Lors de la comparaison de chaînes, l'opérateur de comparaison compare des chaînes entières.

LIKE est un opérateur de chaîne qui compare caractère par caractère.

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+
2
vipin 28 mai 2018 à 11:51

L'opération '=' recherche une correspondance exacte tandis que l'opération LIKE fonctionne plus comme une correspondance de modèle avec '%' étant similaire à '*' dans les expressions régulières.

Donc, si vous avez des entrées avec

  1. Bonne qualité
  2. Plus de bonne qualité

Seul LIKE obtiendra les deux résultats.

En ce qui concerne la chaîne d'échappement, je ne suis pas sûr de l'endroit où cela est généré, mais cela ressemble à un échappement standardisé pour obtenir cela valide pour SQL.

2
Stephan Wiehr 30 mai 2018 à 12:35