MongoDB bedingte Aggregatabfrage für eine HABTM-Beziehung (Mongoid, RoR)?

8

Rails 4.2.5 , Mongoid 5.1.0

Ich habe drei Modelle - Mailbox , Communication und Message .

mailbox.rb

%Vor%

communication.rb

%Vor%

message.rb

%Vor%

Ich verwende den Authentifizierungs-Gem devise , der Zugriff auf den current_user -Helfer gibt, der auf den aktuellen angemeldeten Benutzer zeigt.

Ich habe eine Abfrage für einen Controller erstellt, der die folgenden Bedingungen erfüllt: Erhalten Sie die current_user s mailbox , deren communication durch das box -Feld gefiltert werden, wobei box == 'inbox' . Es wurde so konstruiert ( und arbeitet ):

current_user.mailbox.communications.where(:box => 'inbox')

Mein Problem tritt auf, wenn ich versuche, auf dieser Abfrage aufzubauen. Ich möchte Abfragen so verketten, dass ich nur messages erhalte, wessen last Nachricht nicht von current_user stammt. Ich kenne die .last-Methode, die den neuesten Datensatz zurückgibt. Ich habe die folgende Abfrage erstellt, kann aber nicht verstehen, was angepasst werden müsste, damit es funktioniert:

current_user.mailbox.communications.where(:box => 'inbox').where(:messages.last.from_user => {'$ne' => current_user})

Diese Abfrage erzeugt das folgende Ergebnis: undefined method 'from_user' for #<Origin::Key:0x007fd2295ff6d8>

Ich bin derzeit in der Lage, dies zu erreichen, indem ich Folgendes tue, von dem ich weiß, dass es sehr ineffizient ist und ich es sofort ändern möchte:

mb = current_user.mailbox.communications.inbox

comms = mb.reject {|c| c.messages.last.from_user == current_user}

Ich möchte diese Logik von Ruby auf die eigentliche Datenbankabfrage verschieben. Vielen Dank im Voraus an jeden, der mich dabei unterstützt, und bitte lass es mich wissen, wenn hier mehr Information hilfreich ist.

    
ljlozano 17.02.2016, 20:19
quelle

1 Antwort

0

Ok, was hier passiert, ist irgendwie unordentlich und hat damit zu tun, wie schlau Mongoid tatsächlich sein kann, wenn es um Assoziationen geht.

Genauer gesagt, wie Abfragen beim Überqueren zweier Assoziationen aufgebaut werden.

Bei Ihrer ersten Anfrage:

%Vor%

Das ist cool mit Mongoid, weil das eigentlich nur in 2 db-Aufrufe entartet:

  1. Ruft das aktuelle Postfach für den Benutzer ab
  2. Mongoid erstellt ein Kriterium direkt gegen die Kommunikationssammlung mit einer where-Anweisung, die besagt: Verwenden Sie die Postfach-ID aus Element 1 und filtern Sie nach Box = Posteingang.

Wenn wir jetzt zu Ihrer nächsten Anfrage kommen,

%Vor%

Ist, wenn Mongoid verwirrt wird.

Hier ist das Hauptproblem: Wenn Sie "wo" verwenden, fragen Sie die Sammlung ab, in der Sie sich gerade befinden. Sie werden keine Verknüpfungen überschreiten .

Was die where (: messages.last.from_user = & gt; {'$ ne' = & gt; current_user}) tatsächlich macht, ist nicht , um die Nachrichtenzuordnung zu überprüfen. Was Mongoid tatsächlich macht, ist das Durchsuchen des Kommunikationsdokuments nach einer Eigenschaft, die einen JSON-Pfad ähnlich wie folgt haben würde: communication ['messages'] ['last'] ['from_user'].

Nun, da Sie wissen, warum, können Sie das erreichen, was Sie wollen, aber es wird ein bisschen mehr Schweiß als die entsprechende ActiveRecord-Arbeit erfordern.

Hier erfahren Sie mehr über das, was Sie wollen:

%Vor%

Ich bin mir nicht sicher, ob mein Code 100% ist (Sie müssen wahrscheinlich die Feldnamen in den Dokumenten überprüfen, um sicherzustellen, dass ich die richtigen durchsuche), aber ich denke, Sie erhalten das allgemeine Muster.

>     
TreyE 16.05.2016 22:30
quelle