8
votes

Comment combiner les résultats de deux questions sur le même modèle?

Je dois retourner exactement dix enregistrements pour une utilisation dans une vue. J'ai une requête très restrictive que j'aimerais utiliser, mais je veux une requête moins restrictive en place pour remplir les résultats dans le cas où la première requête ne donne pas dix résultats.

Juste à jouer pendant quelques minutes, Et c'est ce que je suis venu, mais ça ne marche pas. Je pense que cela ne fonctionne pas car la fusion est destinée à combiner des requêtes sur différents modèles, mais je pourrais me tromper. xxx

regardant dans la console, cela force les restrictions dans la liste répertoriée La requête dans Rescue_articles, montrant quelque chose comme: xxx

Je suis sûr qu'il y a une méthode ridiculement facile qui me manque dans la documentation, mais je ne l'ai pas encore trouvé.

EDIT: Ce que je veux faire, c'est de retourner tous les articles dans lesquels la liste est fidèle des vingt-cinq articles les plus récents. Si cela ne me donne pas dix articles, j'aimerais ajouter suffisamment d'articles des articles les plus récents où la liste n'est pas vraie pour obtenir mes dix articles complets.

Edit # 2: En d'autres termes, la méthode de fusion semble corder les requêtes ensemble pour faire une longue requête au lieu de fusionner les résultats. J'ai besoin des dix premiers résultats des deux requêtes (hiérarchisation des articles répertoriés), pas une interrogation longue.


0 commentaires

4 Réponses :


11
votes

Avec votre code initial:

Vous pouvez rejoindre deux tableaux en utilisant + puis obtenir les 10 premiers résultats: P>

  def self.current
      oldest_accepted = Article.published.order('created_at DESC').limit(25).last
      Artcile.published.where(['created_at > ?', oldest_accepted.created_at]).order('listed DESC').limit(10)
  end


11 commentaires

Je ne suis pas sûr de ce que cela ferait. Je vais modifier ma question pour être plus clair.


D'ACCORD. Cela chargerait essentiellement tous les articles publiés, avec toutes les répertoires = TRUE en haut. Alors commandé par créé_at. Ensuite, limitée à 10. Donc, si seulement 3 répertoriés, il en retournerait ces 3 puis 7 à partir de non indiqué. Si vous aviez répertorié 12, il retournerait les 10 premiers.


La raison pour laquelle je ne fais pas est parce que je ne veux pas d'articles inclus qui ne sont pas dans les vingt-cinq les plus récents, qu'ils soient énumérés ou non. Je préférerais avoir des articles non répertoriés remplissant les dix résultats que les articles plus âgés que les vingt-cinq dernières.


Ce n'est toujours pas ce dont j'ai besoin. Mettre la limite (25) La condition de droite donne les 25 premiers du tableau.


Maintenant, vous dirigez la bonne direction, sauf si il n'y a que 3 sur les 25 derniers articles qui sont énumérés? J'ai besoin exactement de 10 enregistrements. Donc, s'il n'y a pas 10 articles répertoriés dans les 25 articles les plus récents, je dois compléter les articles répertoriés avec des articles non répertoriés pour obtenir exactement 10.


La méthode actuelle devrait essentiellement obtenir les 25 articles récents et commander ceux-ci par la liste (True Premier). Il limite ensuite cela à 10. Cela ne fonctionne pas?


C'est tellement proche, mais il ne fait toujours que corder les requêtes dans une longue déclaration: "Charge de l'article (0.3ms) Sélectionnez Articles . * Du Articles Où (publié = 1) Commande par Created_AT Desc, énuméré Desc "


Cela fait le tableau, mais je ne peux pas le manipuler plus comme un objet AR normal (qui arrive dans une vue).


Sale bidouille fonctionne pour l'instant. Je vais marquer le vôtre comme la réponse acceptée pour cela, mais je vais continuer à rechercher un astuce de rails qui me permet de combiner les résultats de deux requêtes sans simplement fusionner les requêtes dans une seule déclaration.


En fait, plus je le regarde, plus je réalise que le hack sale est assez expressif de ce que je veux faire. Je vais juste le laisser seul. Merci.


Lorsque j'utilise cela avec Will_paginate, je reçois méthode non définie pagine 'pour # `



1
votes

Je pense que vous pouvez faire tout cela dans une requête: xxx

i peut avoir le bon ordre de tri de la colonne répertorié, mais cela devrait fonctionner. Vous obtiendrez d'abord tous les éléments énumérés, triés par Created_at Desc, puis des éléments non répertoriés.


3 commentaires

Cela donnerait la priorité aux articles répertoriés de plus de 25 articles les plus récents sur les nouveaux articles non rendus, ce dont j'ai besoin.


J'ai dû louper quelque chose. En mettant d'abord le "ASC énumétaire", il triera la table avec toutes les valeurs NULL ou 0 dans la liste indiquée (non enregistrée) au début du résultat. S'il y en a 2, ils seraient en haut, alors vous auriez les éléments les plus récents avec une 1 dans la colonne répertoriée (AKA ci-dessous). Si ce n'est pas la bonne compréhension, vous pouvez peut-être modifier la question avec quelques échantillons d'enregistrements pour montrer ce que le résultat devrait ressembler.


Le "ASC énumété" met une priorité sur les articles non cotés, ce qui est le contraire de ce dont j'ai besoin.



3
votes

Tout ce que vous avez à faire est de résumer les requêtes:

result1 = Model.where(condition)
result2 = Model.where(another_condition)

# your final result
result = result1 + result2


2 commentaires

FYI: Cela ne fonctionne pas avec AR: AssociationRelations. Nométhoderror: méthode non définie `<< 'pour #


Cela va combiner / fusionnera l'amende des résultats finaux. Mais il perd ses propriétés d'enregistrement actif. Vous ne pouvez pas utiliser d'autres étanches à ce sujet.



4
votes

Si vous voulez un objet activeCord :: relation code> à la place d'un tableau, vous pouvez utiliser:

  • ACIVERCORDUNION GEM . P>

    Installation GEM: GEM Installez Active_Record_Union Code> et utilisez: P>

    class Article < ActiveRecord::Base
      include ActiveRecord::UnionScope
      ...
      def self.current
        union_scope(Article.rescue_articles, Article.listed_articles).limit(10)
      end
      ...
    end
    
  • Module Unionscope . P>

    Créer un module unionscope (lib / actif_record / union_scope.rb). p>

    module ActiveRecord::UnionScope
      def self.included(base)
        base.send :extend, ClassMethods
      end
    
      module ClassMethods
        def union_scope(*scopes)
          id_column = "#{table_name}.id"
           if (sub_query = scopes.reject { |sc| sc.count == 0 }.map { |s|   "(#{s.select(id_column).to_sql})" }.join(" UNION ")).present?
            where "#{id_column} IN (#{sub_query})"
          else
            none
          end
        end
      end
    end
    


2 commentaires

Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses uniquement uniquement peuvent devenir invalides si la page liée change. - de l'avis


Merci pour votre avis @petezurich! J'ai édité ma réponse.