11
votes

N + 1 problème en mongoïde

J'utilise Mongoid pour travailler avec MongoDB dans des rails.

Ce que je cherche, c'est quelque chose comme un enregistrement actif inclure . Actuellement, j'ai échoué à trouver une telle méthode dans Mongoid Orm.

Tout le monde sait comment résoudre ce problème en Mongoïde ou peut-être à Mongomapper, qui est connu comme une autre bonne alternative.


1 commentaires

Veuillez envisager de réévaluer vos réponses maintenant que quelque temps est passé. Je crois qu'il y a quelques erreurs de conception autour de ce sujet.


8 Réponses :


13
votes

Mise à jour: Cela fait deux ans que j'ai posté cette réponse et que les choses ont changé. Voir Réponse de Tybro0103 pour plus de détails.


Ancienne réponse

basé sur la documentation des deux pilotes, aucun d'entre eux ne supporte ce que vous recherchez. Probablement parce que cela ne résoudrait rien .

Le : Inclure Fonctionnalité de ActionCord résout le problème N + 1 pour les bases de données SQL . En disant à ActiveRecord Quelles sont des tableaux associés à inclure, il peut construire une seule requête SQL, en utilisant les relevés rejoindre . Cela entraînera une seule base de données, quelle que soit la quantité de tables que vous souhaitez interroger.

MongoDB ne vous permet que de Requête une seule collection à la fois . Il ne supporte rien de tel qu'un rejoindre . Donc, même si vous pouviez dire à Mongoid quelles autres collections, il aurait toujours d'exécuter une requête séparée pour chaque collection supplémentaire.


2 commentaires

Ce n'est pas correct. Les rails ': incluent les options ne font pas une jointure. Il est impatient de charges. Le chargement désireux est nécessaire pour SQL et Mongo. Il vous empêche d'interroger la même collection pendant que vous êtes dans une boucle et que vous interrogeez la collection une fois avant de commencer la boucle.


Considérez une vue avec une liste de messages et sous chaque poste est une liste de commentaires. Si vous ne savez pas de charger, vous devez interroger les collections de commentaires une fois par message (N + 1). Heureusement, Mongoid a inclut () ... Voir ma réponse.



0
votes

Vous avez besoin de mettre à jour votre schéma pour éviter ce n + 1 Il n'y a pas de solution à MongoDB pour faire une certaine assiette.


0 commentaires

0
votes

Incorporer les enregistrements / documents détaillés dans le dossier principal / document.


0 commentaires

5
votes

ActiveRecord : Inclure code> ne fait généralement pas une jointure complète pour peupler des objets Ruby. Cela fait deux appels. D'abord pour obtenir l'objet parent (dire un post) puis un deuxième appel pour tirer les objets associés (commentaires qui appartiennent au poste).

Mongoïde fonctionne essentiellement de la même manière pour les associations référencées. P>

<%- @post.comments.each do |comment| -%>
    VIEW CODE
<%- end -%>


1 commentaires

Ceci est également incorrect. Considérez le cas où vous affichez une liste de messages avec une liste de commentaires sous chaque poste. Utilisation de POST.COMMENTS Pendant que vous êtes en boucle via les messages générera une nouvelle requête chaque fois que si vous utilisez des rails ': Inclure . Heureusement, Mongoid a inclut () ... Voir ma réponse.




16
votes

4 commentaires

juste pour ajouter un commentaire. Vous devez être activé Identifier la carte pour le faire fonctionner mongoid.org/fr/mongoid/docs/identity_map .html


MONGOID Comprend prend en charge les relations directes de chargement désireuses, mais ne prend pas en charge le chargement impatient de charger des relations à deux niveaux ou un chargement impatiété un polymorphe appartient à . Si vous avez besoin de ces fonctionnalités, j'ai créé un Bibliothèque qui s'étend au Mongoïde pour supporter ces cas d'utilisation.


@Vp. Mongoid5 - Pas plus de carte d'identité. Donc pas nécessaire plus.


@Herzelguinness Yup, après 3 ans, beaucoup de choses changent .. Droite!



7
votes

Bien que les autres réponses soient correctes, dans les versions actuelles de Mongoids, la méthode comprend la meilleure façon d'atteindre les résultats souhaités. Dans les versions précédentes où l'inclut n'était pas disponible, j'ai trouvé un moyen de se débarrasser du numéro N + 1 et de penser qu'il valait la peine de mentionner.

Dans mon cas, c'était un numéro N + 2. P>

def index
  @judges ||= Awards::Api::Judge.where(:user_id.exists => true)
  @users = User.where(:_id.in => @judges.map(&:user_id)).to_a
  @photos = Awards::Api::Judges::Photo.where(:_id.in => @judges.map(&:photo_id)).to_a
  respond_with @judges
end


4 commentaires

Pourquoi ne voudriez-vous pas juste faire juge.where (...). Comprend (: photo,: utilisateur) ?


C'était une solution avant que ce soit «inclut» a été ajouté en Mongoïde et peut encore être bénéfique pour la compréhension.


"Bien que les autres réponses soient correctes, il n'existe pas de méthode d'adhésion à travers les collections, j'ai trouvé un moyen de se débarrasser du numéro N + 1" ... semble indiquer que cette réponse résout le problème N + 1 tandis que d'autres réponses ne pas. Cependant, en utilisant inclut résoudra le problème N + 1 et il avait été mis en œuvre à Mongoïde plus d'un an avant que cela ait été publié, autant de réponses plus anciennes l'ont renvoyée.


Je suis d'accord. Je n'ai pas dit que j'ai posté cette solution avant 'inclut' a été ajouté. J'ai déclaré que cette était une solution avant 'inclut' a été ajoutée. et je l'ai posté à des fins éducatives de toute façon. Je ne pense pas non plus que quelque chose qu'il mentionne indique que les autres réponses ne résolvent pas le problème. Presque l'opposé, j'ouvre avec "les autres réponses sont correctes".



0
votes

Dans mon cas, je n'ai pas eu toute la collection, mais un objet qui a causé n + 1 (la balle dit que).

SO plutôt que d'écrire ci-dessous qui provoque N + 1 P>

Quote.includes(:provider).find(quote._id).provider.officialname


0 commentaires