2017-11-17 1 views
1

Ich möchte eine Activerecord-Abfrage schreiben, die so etwas wie dies verhält:Gibt es eine Möglichkeit, nach leeren Arrays zu suchen, die von ActiveRecord-Abfragen zurückgegeben werden?

User.joins(:comment).where(comments: {replies: []}) 

die Benutzer gibt, wo ihre Kommentare keine Antworten haben.

User.first.comment.first.replies => [] returns an empty array 

Ich brauche dies nur eine ActiveRecord-Beziehung, also wird die Verwendung von Ruby-Code nicht funktionieren. Gibt es eine Möglichkeit, mit ActiveRecord nach leeren Arrays zu suchen?

Edit: Beispiel Schema

create_table "users", force: :cascade do |t| 
t.string "email", 
t.string "password" 
end 

create_table "comments" do |t| 
t.string "content" 
end 

create_table "replies" do |t| 
t.string "content" 
end 

User.rb

class User < ActiveRecord::Base 
has_many :comments 
end 

Comment.rb

class Comment < ActiveRecord::Base 
belongs_to :user 
has_many :replies 
end 

Reply.rb

class Reply < ActiveRecord::Base 
belongs_to :comment 
belongs_to :user 
end 

Dies sind nur Beispielmodelle, aber dies sollte das Problem mit Modellen veranschaulichen, die diese damit verbinden.

Wenn also ein Benutzer (mit der ID 1) 3 Kommentare erstellt hat und nur 1 dieser 3 Kommentare eine Antwort darauf hat, wie würde ich die anderen 2 Kommentare in einer ActiveRecord-Beziehung erhalten?

+0

Könnten Sie bitte das Schema für die Kommentartabelle posten? – SRack

+0

Die Modelle, die ich verwendete, waren nur Beispiele, aber ich kann ein Beispielschema mit diesen Modellen erstellen, wenn das hilfreich ist. – JimmyW

+0

Ich war hauptsächlich daran interessiert, die Antworten Spalte und wie es gespeichert ist (/ wenn ich Missverständnisse und es ist eine andere Tabelle) zu erfassen. Ich kann Ihnen ein Beispiel geben, wie das funktioniert, aber um den optimalen Ansatz zu erhalten, würde ich ein bisschen mehr brauchen, wie die Daten gespeichert sind. Bearbeiten: auch gut sein, um die Modellstruktur und wie die Tabellen zugeordnet sind. – SRack

Antwort

3

Sie können nach Design einfacher machen mit counter_cache

hinzufügen counter_cache in Antworten

class Reply < ActiveRecord::Base 
belongs_to :comment, counter_cache: true 
belongs_to :user 
end 

Zähler Spalte in Kommentartabelle hinzufügen

create_table "comments" do |t| 
t.string "content" 
t.integer "replies_count" 
end 

Einfache Verwendung Bedingung für REPLIES_COUNT

User.joins(:comment).where(comments: {replies_count: 0}) 

Für weitere Informationen siehe rails doc

0

Sie benötigen einen LEFT JOIN von comments zu replies verwenden, die alle Kommentare unabhängig von zurückgeben wird, ob eine Antwort für jeden Kommentar da war. Die übliche Verbindung in Schienen, d. H. Verbindung, die ausgeführt wird, wenn Sie @comment.replies oder User.joins(comments: :replies) tun, ist eine INNER JOIN. ActiveRecord kein geschicktes DSL für das Schreiben von Abfragen kommen gelassen, aber sie in der folgenden Art und Weise erlaubt:

# Find all users who have at least one comment with no replies 
User.joins(:comments) 
    .joins("LEFT JOIN replies ON replies.comment_id = comments.id") 
    .where("replies.id IS NULL") 

# Find all comments for a user that don't have replies 
@user.comments 
    .joins("LEFT JOIN replies ON replies.comment_id = comments.id") 
    .where("replies.id IS NULL") 

ich die beiden Schnipsel enthalten, weil in Ihrer Frage unklar war, ob Sie die Benutzer finden wollten oder die Kommentare für einen bestimmten Benutzer ohne Antworten.

Der where("replies.id IS NULL") ist der Filter, der jeden Kommentar in LEFT JOIN ohne übereinstimmende Antworten findet und liefert das gewünschte Ergebnis. Dies ist ein sehr üblicher SQL Trick, den es für zukünftiges Datengrabeln zu beachten gilt.

Verwandte Themen