Anfänge, wenn ich ein Histogramm aller Items
aufzubauen versuche, die einen Order
Start zwischen einem gegebenen Satz von Daten basierend auf genau, was der Punkt war (:name_id
) und die Frequenz dieser :name_id
, war ich mit dem folgenden Code:Wie ActiveRecord Relations kombinieren? Merge funktioniert nicht?
dates = ["May 27, 2016", "May 30, 2016"]
items = Item.joins(:order).where("orders.start >= ?", dates.first).where("orders.start <= ?", dates.last)
histogram = {}
items.pluck(:name_id).uniq.each do |name_id|
histogram[name_id] = items.where(name_id:name_id).count
end
Dieser Code funktionierte FINE.
Jetzt versuche ich jedoch, ein Histogramm zu erstellen, das expansiver ist. Ich möchte immer noch die Frequenz von :name_id
über einen gewissen Zeitraum hinweg erfassen, aber jetzt möchte ich diese Zeit durch Order
starten und beenden. Ich habe jedoch Probleme, die ActiveRecord Relations, die den Abfragen folgen, zu kombinieren. Insbesondere dann, wenn meine Fragen sind wie folgt:
items_a = Item.joins(:order).where("orders.start >= ?", dates.first).where("orders.start <= ?", dates.last)
items_b = Item.joins(:order).where("orders.end >= ?", dates.first).where("orders.end <= ?", dates.last)
Wie trete ich die 2-Abfragen, so dass mein Code unten, dass auf Abfrage wirkt Objekte noch funktioniert?
items.pluck(:name_id).each do |name_id|
histogram[name_id] = items.where(name_id:name_id).count
end
Was ich habe versucht:
+
, aber das ist natürlich nicht funktioniert, weil es das Ergebnis in einem Array dreht, wo Methoden wie pluck
nicht funktionieren:
(items_a + items_b).pluck(:name_id)
=> error
merge
, das ist, was alle SO-Antworten zu sagen scheinen ... aber es funktioniert nicht für mich, weil, wie die Dokumente sagen, merge
die Kreuzung herausfindet, so ist mein Ergebnis wie folgt:
items_a.count
=> 100
items_b.count
=> 30
items_a.merge(items_b)
=> 15
FYI derzeit habe ich affe-patched dies mit dem unten, aber es ist nicht sehr ideal. Danke für die Hilfe!
name_ids = (items_a.pluck(:name_id) + items_b.pluck(:name_id)).uniq
name_ids.each do |name_id|
# from each query object, return the ids of the item objects that meet the name_id criterion
item_object_ids = items_a.where(name_id:name_id).pluck(:id) + items_b.where(name_id:name_id).pluck(:id) + items_c.where(name_id:name_id).pluck(:id)
# then check the item objects for duplicates and then count up. btw I realize that with the uniq here I'm SOMEWHAT doing an intersection of the objects, but it's nowhere near as severe... the above example where merge yielded a count of 15 is not that off from the truth, when the count should be maybe -5 from the addition of the 2 queries
histogram[name_id] = item_object_ids.uniq.count
end
Welche Version von Rails verwenden Sie? Die neuesten Versionen (Vorabversionen) unterstützen 'items_a.or (items_b)'. – Raffael
Eine schnelle Lösung wäre, die gesamte Bedingung mit SQL zu beschreiben: 'Item.joins (: order) .where (" (orders.start BETWEEN: min UND: max) OR (orders.end ZWISCHEN: min UND: max) " , min: dates.first, max: dates.last) ' – Raffael
Als Alternative fügt das Juwel' squeel 'etwas SQL-Algebra-Gutheit zu ActiveRecord hinzu. – Raffael