9 Stimmen

Rails speichert eine paginierte Sammlung im Cache

Nur Recherchen über die beste Möglichkeit, eine paginierte Sammlung von Elementen zu zwischenspeichern. Verwende derzeit jbuilder, um JSON auszugeben, und habe mit verschiedenen cache_key-Optionen experimentiert.

Das beste Beispiel, das ich gesehen habe, verwendet das updated_at des neuesten Datensatzes plus die Anzahl der Elemente in der Sammlung.

def cache_key
      pluck("COUNT(*)", "MAX(updated_at)").flatten.map(&:to_i).join("-")

definiert hier: https://gist.github.com/aaronjensen/6062912

Dies funktioniert jedoch nicht für paginierte Elemente, bei denen ich immer 10 Elemente in meiner Sammlung habe.

Gibt es dafür irgendwelche Workarounds?

10voto

Jacob Evan Shreve Punkte 1092

Mit einer paginierten Sammlung bekommen Sie einfach ein Array. Jeder Versuch, das Array zu ändern, um einen Cache-Schlüssel einzuschließen, wäre etwas umständlich. Ihr bester Einsatz ist einfach die Verwendung der Cache-Methode, um auf Basis einer Sammlung zu Sammlung einen Schlüssel zu generieren.

Sie können viele Dinge an die Cache-Methode übergeben, um einen Schlüssel zu generieren. Wenn Sie immer 10 Elemente pro Seite haben, denke ich nicht, dass die Anzahl sehr wertvoll ist. Die Seitenzahl und das zuletzt aktualisierte Element wären jedoch wichtig.

cache ["v1/items_list/page-#{params[:page]}", @items.maximum('updated_at')] do

würde einen Cache-Schlüssel wie

v1/items_list/page-3/20140124164356774568000

Bei der russischen Puppen-Cache sollten Sie auch jedes Element in der Liste zwischenspeichern

# index.html.erb
<%= cache ["v1/items_list/page-#{params[:page]}", @items.maximum('updated_at')] do %>

  <%= render @items %>
<% end %>

# _item.html.erb
<%= cache ['v1', item] do %>

<% end %>

3voto

kogre Punkte 131

Das Zwischenspeichern von paginierten Sammlungen ist knifflig. Der übliche Trick, die Sammlungszahl und max updated_at zu verwenden, gilt meistens nicht!

Wie du gesagt hast, ist die Sammlungszahl eine gegebene Größe und daher irgendwie nutzlos, es sei denn, du erlaubst dynamische per_page Werte.

Das neueste updated_at ist vollständig abhängig von der Sortierung deiner Sammlung.

Stell dir vor, ein neuer Datensatz wird hinzugefügt und landet auf Seite eins. Das bedeutet, dass ein Datensatz, der zuvor auf Seite 1 war, jetzt auf Seite 2 erscheint. Ein zuvor auf Seite 2 befindlicher Datensatz wird jetzt zu Seite 3. Wenn der neue Datensatz auf Seite 2 nicht aktualisierter ist als der vorherige Maximalwert, bleibt der Zwischenspeicher-Schlüssel gleich, aber die Sammlung nicht! Das Gleiche passiert, wenn ein Datensatz gelöscht wird.

Nur wenn du garantieren kannst, dass neue Datensätze immer auf der letzten Seite landen und keine Datensätze gelöscht werden, ist die Verwendung des max updated_at ein solider Ansatz.

Als Lösung könntest du die Gesamtanzahl der Datensätze und das Gesamtmaximal updated_at im Zwischenspeicher-Schlüssel einschließen, zusätzlich zur Seitennummer und dem per_page Wert. Dies erfordert zusätzliche Abfragen, kann sich aber je nach Datenbankkonfiguration und Datensatzanzahl lohnen.

Eine weitere Lösung besteht darin, einen Schlüssel zu verwenden, der eine reduzierte Form des tatsächlichen Inhalt der Sammlung berücksichtigt. Zum Beispiel unter Berücksichtigung aller Datensatz-IDs.

Wenn du postgres als Datenbank verwendest, könnte dir dieses Tool helfen, obwohl ich es selbst noch nie benutzt habe. https://github.com/cmer/scope_cache_key

Und der Rails 4 Fork: https://github.com/joshblour/scope_cache_key

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X