Comment exprimer un PAS DANS la requête avec ActiveRecord/Rails?
Juste de mettre à jour cette car il semble que beaucoup de gens viennent à ce, si vous êtes à l'aide de Rails de 4 à examiner les réponses par Lê Trung " et VinniVidiVicci.
Topic.where.not(forum_id:@forums.map(&:id))
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
Je l'espère, il y a une solution simple qui n'implique pas de find_by_sql
, si non, alors je suppose que vous avez à travailler.
J'ai trouvé cet article qui référence ce:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
qui est le même que
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
Je me demandais si il existe un moyen de faire NOT IN
avec que, comme:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
- Comme pour info, Datamapper a eu un soutien spécifique pour les PAS DANS. Exemple:
Person.all(:name.not => ['bob','rick','steve'])
- désolé d'être ignorant, mais qu'est-ce que Datamapper? est la partie de rails 3?
- mapper des données est une autre façon de stocker des données, il remplace Active Record avec une structure différente, et ensuite, vous écrivez votre modèle des choses telles que des requêtes, différemment.
Vous devez vous connecter pour publier un commentaire.
Je suis en utilisant ceci:
Où
actions
est un tableau avec:[1,2,3,4,5]
Edit:
Pour les Rails 4 notation:
actions
est nul ou videTopic.where('id NOT IN (?)', (actions.empty? ? '', actions)
. Il serait encore briser sur le zéro, mais je trouve que le tableau que vous transmettez est généralement généré par un filtre qui sera de retour[]
à tout le moins, et jamais nul. Je recommande de vérifier Squeel, DSL sur le dessus de l'Enregistrement Actif. Alors que vous pourriez faire:Topic.where{id.not_in actions}
, nil/vide/ou autrement..empty?
pour.blank?
et vous êtes néant-preuve[]
ounil
. Vous vous retrouvez avecid NOT in (null)
. Pour obtenir autour de cette utilisationpresence
, comme suit:Topic.where( 'id NOT IN (?)', actions.presence || "" )
Array.wrap(actions)
Pour info, Dans les Rails 4, vous pouvez utiliser
not
syntaxe:Vous pouvez essayer quelque chose comme:
Vous pourriez avoir besoin de faire
@forums.map(&:id).join(',')
. Je ne me souviens pas si les Rails de l'argument dans un fichier CSV la liste si elle est énumérable.Vous pourriez aussi le faire:
À L'Aide Arel:
ou, si l'on préfère:
et depuis des rails 4:
Veuillez noter que, finalement, vous ne voulez pas que le forum_ids à l'id de la liste, mais plutôt une sous-requête, si oui, alors vous devez faire quelque chose comme ça avant de se les sujets:
de cette façon, vous obtenez tout en une seule requête: quelque chose comme:
Également remarquer que finalement vous ne voulez pas faire cela, mais plutôt une jointure - ce qui pourrait être plus efficace.
EXPLAIN
!Étendre sur @Lê Trung réponse, dans les Rails 4, vous pouvez effectuer les opérations suivantes:
Et vous pourriez prendre un pas de plus.
Si vous avez besoin d'abord de filtrer uniquement les Sujets publiés et puis filtrer les identifiants que vous ne voulez pas, vous pourriez faire ceci:
Rails 4 c'est tellement plus facile!
La solution retenue échoue si
@forums
est vide. Pour contourner ce que j'avais à faireOu, si à l'aide de Rails 3+:
La plupart des réponses ci-dessus devraient suffire à vous, mais si vous faites beaucoup plus de ces prédicat et des combinaisons complexes découvrez Squeel. Vous serez en mesure de faire quelque chose comme:
Vous voudrez peut-être avoir un coup d'oeil à la meta_where plugin par Ernie Miller. Votre instruction SQL:
...pourrait être exprimée ainsi:
Ryan Bates de Railscasts créé un nice screencast expliquant MetaWhere.
Ne sais pas si c'est ce que vous cherchez, mais à mes yeux, il est certainement mieux que l'embedded SQL de la requête.
Ces forum ids être travaillé de façon pragmatique? par exemple, pouvez-vous trouver ces forums en quelque sorte - si c'est le cas, vous devriez faire quelque chose comme
Qui serait plus efficace que de faire un SQL
not in
De cette façon optimise pour des raisons de lisibilité, mais il n'est pas aussi efficace en termes de requêtes de base de données:
Le post original mentionne spécifiquement en utilisant des Id numériques, mais je suis venu ici à la recherche pour la syntaxe pour faire un PAS DANS un tableau de chaînes de caractères.
ActiveRecord se débrouillera bien pour vous aussi:
Vous pouvez utiliser sql dans vos conditions:
Ferroutage hors de jonnii:
l'aide d'arracher plutôt que de cartographier les éléments
trouvé via railsconf 2012 10 choses que vous ne connaissez pas les rails de pourrait le faire
Lorsque vous interrogez un tableau vide d'ajouter "<<" 0 " à la matrice dans le cas où le bloc de sorte qu'il ne retourne "NULL" et de briser la requête.
Si des mesures pourraient être vide ou vide tableau.
Topic.where("id NOT IN (?)", actions.presence || [0])
Ici est de plus en plus complexe "n'est pas" de la requête, en utilisant une sous-requête dans les rails à l'aide de 4 squeel. Bien sûr, très lente par rapport à l'équivalent sql, mais bon, il fonctionne.
Les 2 premières méthodes dans le champ d'application d'autres étendues qui déclarent les alias cavtl1 et tl1. << est pas dans l'opérateur dans squeel.
Espère que cela aide quelqu'un.