Sie möchten in Rails 3 Datensätze ohne verknüpfte Datensätze finden
Betrachten Sie einen einfachen Verband...
class Person
has_many :friends
end
class Friend
belongs_to :person
end
Was ist der sauberste Weg, um alle Personen, die KEINE Freunde haben, die in ARel und/oder meta_where?
Und was ist dann eine has_many :through version
class Person
has_many :contacts
has_many :friends, :through => :contacts, :uniq => true
end
class Friend
has_many :contacts
has_many :people, :through => :contacts, :uniq => true
end
class Contact
belongs_to :friend
belongs_to :person
end
Ich wirklich nicht wollen, zu verwenden counter_cache - und ich von dem, was ich gelesen habe, es funktioniert nicht mit has_many :through
Ich will nicht zu ziehen den ganzen person.friends records und eine Schleife in Ruby - ich möchte eine Abfrage/Rahmen, die ich verwenden können, mit der meta_search gem
Ich nicht Sinn der Leistung Kosten der Abfragen
Und je weiter Weg vom eigentlichen SQL-desto besser...
InformationsquelleAutor der Frage craic.com | 2011-03-15
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist immer noch ziemlich nahe an SQL, aber es sollte jeder mit keine Freunde in der erste Fall:
InformationsquelleAutor der Antwort Unixmonkey
Besser:
Für die hmt, es ist im Grunde die gleiche Sache, die Sie verlassen sich auf die Tatsache, dass eine person mit keine Freunde haben auch keine Kontakte:
Update
Haben Sie eine Frage zu
has_one
in den Kommentaren, so dass nur der Aktualisierung. Der trick hier ist, dassincludes()
erwartet den Namen des Vereins, aber diewhere
erwartet den Namen der Tabelle. Für einehas_one
der Verein wird in der Regel ausgedrückt in der Einzahl, so dass die änderungen, aber diewhere()
Teil bleibt wie es ist. Also, wenn einPerson
nurhas_one :contact
dann Ihre Aussage wäre:Update 2
Jemand fragte über die inverse, Freunde mit keine Menschen. Wie ich unten kommentiert, dieser tatsächlich machte mir klar, dass das Letzte Feld (oben:
:person_id
) tatsächlich nicht mit dem Modell, die Sie zurückgeben, es hat nur ein Feld in der join-Tabelle. Sie sind alle gehen, umnil
so kann es jedem von Ihnen. Dies führt zu einer einfacheren Lösung zu den oben genannten:Und dann wechseln diese die Rückkehr der Freunde, ohne Menschen wird auch einfacher, Sie ändern nur die Klasse an der front:
Update 3 - Schienen 5
Dank @Anson für die hervorragende Rails-5-Lösung (gib ihm ein paar +1s für seine Antwort weiter unten), können Sie
left_outer_joins
zu vermeiden, laden der Verein:Habe ich es hier, damit die Leute es finden, aber er verdient den +1s. Tolle Ergänzung!
InformationsquelleAutor der Antwort smathy
smathy hat eine gute Rails 3 ist die Antwort.
Für Schienen 5, die Sie verwenden können
left_outer_joins
zu vermeiden, laden der Verein.Check-out die api-docs. Eingeführt wurde Sie im pull-request #12071.
InformationsquelleAutor der Antwort Anson
Personen, die keine Freunde haben
Oder mit mindestens einem Freund
Können Sie dies mit Arel durch die Einrichtung von Verwaltungsbereichen für
Friend
Und dann, für Personen, die mindestens einen Freund:
Den friendless:
InformationsquelleAutor der Antwort novemberkilo
Sowohl die Antworten von dmarkow und Unixmonkey mir, was ich brauche - Danke!!!
Ich habe sowohl in meinem real-app und bekam timings für Sie - Hier sind die zwei Bereiche:
Lief mit einem "richtigen" app - kleiner Tisch mit ~700 "Personen" - Datensätze - Durchschnitt von 5 läuft
Unixmonkey Ansatz (
:without_friends_v1
) 813ms /Abfragedmarkow Ansatz (
:without_friends_v2
) 891ms /Abfrage (~ 10% langsamer)Aber dann fiel mir ein, dass ich nicht brauchen, den Anruf zu
DISTINCT()...
ich bin auf der Suche nachPerson
Datensätze mit KEINEContacts
- also Sie müssen nurNOT IN
die Liste der Kontaktperson_ids
. So habe ich versucht, dieses Umfang:, Erhält das gleiche Ergebnis, aber mit einem Durchschnitt von 425 ms/Aufruf - fast die Hälfte der Zeit...
Nun brauchst du die
DISTINCT
in anderen ähnlichen Abfragen - aber für meinen Fall scheint dies gut zu funktionieren.Vielen Dank für Ihre Hilfe
InformationsquelleAutor der Antwort craic.com
Leider sind Sie wahrscheinlich auf der Suche auf eine Lösung mit SQL, aber Sie können legen Sie es in einen Rahmen und dann nur mit, dass Umfang:
Dann, Sie zu erhalten, können Sie nur
Person.without_friends
, und Sie können auch die Kette mit anderen Arel Methoden:Person.without_friends.order("name").limit(10)
InformationsquelleAutor der Antwort Dylan Markow
Auch, heraus zu filtern, von einem Freund zum Beispiel:
InformationsquelleAutor der Antwort Dorian
Einer not EXISTS korrelierte Unterabfrage sollte schnell sein, besonders, da die Zeilenanzahl und das Verhältnis von untergeordneten zu übergeordneten Datensätzen erhöht.
InformationsquelleAutor der Antwort David Aldridge