Ich bin immer wieder auf dasselbe Problem gestoßen und habe keine Lösung gefunden, die ich wirklich für optimal hielt.
Angenommen, Sie haben in einer App eine geordnete Liste und lassen den Benutzer diese Reihenfolge per Drag & Drop oder so ändern. Sie möchten, dass die Änderungen in der Reihenfolge beibehalten werden. Wie modellierst du das?
Wie soll ich einen erholsamen Service für eine geordnete Listenressource entwerfen?
Wie soll ich insbesondere das Modell einer erholsamen Ressource entwerfen list
und item
modellieren? Das häufigste Design, das ich gesehen habe, ist die item
Entität mit einer order
oder position
Eigenschaft. Ein anderer Ansatz, den ich gehört habe, ist eine doppelt verknüpfte Liste der Elemente.
Was ist ein Ansatz, der nicht zu viel in die Datenbank schreibt und für Clients im Allgemeinen schnell aktualisiert und gelesen werden kann? Wie sollen die Endpunkte angezeigt werden?
quelle
Antworten:
Die Darstellung einer geordneten Liste ist eines der schwierigen Probleme bei relationalen Datenbanken. Das Hinzufügen einer Positionseigenschaft zur Liste-Mitgliedschafts-Beziehung ist die häufigste Methode, da Sie die geordnete Liste einfach abrufen können, indem Sie sie
ORDER BY position
zu Ihrer SQL-Abfrage hinzufügen , und weil Sie Elemente einfach in die Mitte der Liste einfügen können, indem Sie den Durchschnitt bilden Werte des vorherigen und nachfolgenden Listenmitglieds, vorausgesetzt, die Position ist eher ein Float als eine Ganzzahl.Die Verwendung von doppelt verknüpften Listen sollte vermieden werden, da es leicht ist, die Verknüpfungen versehentlich inkonsistent zu machen und stattdessen ein zyklisches Diagramm oder einen zyklischen Baum zu erhalten.
RESTful-APIs leiden jedoch nicht unter den Einschränkungen relationaler Datenbanken. Sie können einfach etwas tun, das sich natürlich anfühlt, anstatt einen Hack wie eine Positionseigenschaft zu verwenden.
Wenn Sie nur bis zu ein paar hundert Elemente in der Liste haben, übertragen Sie einfach die gesamte Liste in einer Anfrage. Angenommen, wir möchten neu anordnen,
[1, 2, 3, 4]
wo die Listenmitglieder IDs sind, könnten wirDas Backend kann dies dann in die von Ihnen verwendete Datenbanktechnologie übersetzen, der API-Benutzer muss diese Details jedoch nicht berücksichtigen.
Wenn die Liste groß ist und Elemente normalerweise einzeln angefordert werden, können Sie einen Index in der URL zulassen:
Wenn Sie sich für HATEOAS interessieren, kann die Antwort vorige / nächste Links enthalten, um die Navigation zu vereinfachen, wenn die Ressource normalerweise so verbraucht wird. Dies muss jedoch nicht bedeuten, dass Ihre Datenbank auch diese doppelt verknüpfte Liste enthält.
Wenn die Liste sehr groß ist, möchten Sie möglicherweise
ArrayList
ähnliche Vorgänge wieinsert
oderpush
/ verfügbar machenappend
. Ich könnte mir einen Anruf wie vorstellenWenn die Neuordnung ein häufiger Anwendungsfall ist und die Neuordnung sofort festgeschrieben werden sollte, können Sie einen geeigneten Endpunkt in Ihrer API anbieten:
Wenn die neu geordnete Liste explizit festgeschrieben werden soll, ist es einfacher, die neue Bestellung als JSON-Dokument zu übertragen (siehe oben).
Jetzt ist es nicht ganz richtig, dass Sie Ihre API als völlig unabhängig von der von Ihnen verwendeten Datenbanktechnologie anzeigen können. Es ist jedoch am besten, die externe API so frei wie möglich von Implementierungsdetails zu halten. Wenn eine Neuordnung etwa 30 Zeilen berührt, nur um eine Ganzzahlreihenfolge zu aktualisieren, ist das keine große Sache. Tun Sie einfach das Einfachste und aktualisieren Sie immer die gesamte Liste. Wenn Ihre Skalierung eine komplexere Datenbanknutzung erfordert, ziehen Sie es vor, diese Raffinesse im Backend zu erfassen, wo es einfacher ist, die Konsistenz aufrechtzuerhalten.
quelle
Ich denke, die Realisierbarkeit verschiedener Ansätze hängt stark von der zugrunde liegenden Datenbank ab, die verwendet wird.
Dieser Ansatz schlug vor, einen Artikel in der Bestellung zu verschieben:
Dies kann unter Rennbedingungen erfolgen, es sei denn, Sie verfügen über SERIALIZABLE-Transaktionen. Die Standardstufe von READ_COMMITTED in den meisten DBs beseitigt keine Racebedingung!
Ich denke tatsächlich, dass in den meisten Fällen - solange die Liste relativ klein ist - der Ansatz, die vollständige Liste zu ersetzen, weniger Probleme mit den Rennbedingungen hat und die Daten nicht beschädigen kann. Wenn sich der Satz von Elementen geändert hat, seit der Client die Anforderung gestellt hat, können Sie einen 409 (Konflikt) zurückgeben.
Es leidet unter Last-Write-Wins, aber das gilt buchstäblich für JEDE API. Unabhängig davon, welche API Sie implementieren, hat möglicherweise ein anderer Client das Objekt aktualisiert, während Sie eine Seite anzeigen.
quelle