2016-01-22 10 views
5

Wir haben einen graphql-Server (nicht in Javascript geschrieben), der eine paginierte Liste von Objekten bereitstellt. Wir versuchen, uns an die Relay-Spezifikation zu halten, aber wir haben einen interessanten Fall gefunden, der Klärung erforderlich machen könnte.Wie man Cursor verwaltet und in Relay sortiert?

Konkret: Werden Cursor von anderen Eingängen der Verbindung abhängig sein? Ähnlich wie https://github.com/graphql/graphql-relay-js/issues/20 verwendet unsere Verbindung ein sort_key-Argument, das die Sortierreihenfolge der zurückgegebenen Liste bestimmt. Abhängig von der angegebenen Sortierreihenfolge kann die Kante für ein Objekt unterschiedliche Cursorwerte zurückgeben (da der Server jeweils andere Informationen benötigt, um das nächste Objekt zu bestimmen). Ein sorgfältiges Lesen von https://facebook.github.io/relay/docs/guides-mutations.html#range-add deutet jedoch an, dass dies nicht erlaubt ist; Mutationen, die eine neu erstellte Kante zurückgeben, müssen einen einzelnen Cursor zurückgeben, der universell auf alle möglichen Listen angewendet werden kann, in denen diese Kante erscheinen kann. Wie löst Facebook dieses Problem?

Antwort

2

Ja, der Cursor sollte genügend Informationen enthalten, um das Abrufen der nächsten Seite ab diesem Zeitpunkt zu ermöglichen (einschließlich Einschränkungen wie Sortieren und Filtern), aber ob/wie Sie dies tun, liegt an Ihnen, da es Implementierungs- Spezifisch.

Was Mutationen betrifft, können Sie in Ihrer getConfigs() Implementierung rangeBehaviors pro Anruf angeben. Wenn Sie also eine sortierte Ansicht haben, können Sie abhängig von der Sortierreihenfolge anhängen oder vorangehen. Dieses Verhalten gibt an, was Relay auf der Clientseite tun wird, um seinen Speicher zu aktualisieren. Es liegt immer noch in Ihrer Verantwortung sicherzustellen, dass der GraphQL Server alle Informationen erhält, die er benötigt (über Eingabevariablen), um die tatsächliche Mutation korrekt durchzuführen.

+3

ich, dass ich meine Sorge nicht denken, richtig erklärt, ist hier ein konkreteres Beispiel: Sie haben zwei Ansichten auf dem gleichen Relais-paginierte Liste, sortiert nach verschiedenen Feldern. Das gleiche Objekt erscheint in beiden Listen, aber mit unterschiedlichen Cursorn. Sie haben eine Mutation, um ein Objekt zu erstellen, mit einer 'RANGE_ADD', die unterschiedliche Verhaltensweisen für die zwei Ansichten angibt. Die Mutation auf der Serverseite muss einen einzelnen Cursor in der Antwort zurückgeben; Welchen der beiden Cursor gibt es zurück, und was macht die andere Ansicht, weil sie überhaupt keinen Cursor hat? – Evan

+0

Guter Punkt. Es ist möglich, dass wir intern nicht darauf gestoßen sind, weil wir noch keine Mutationen auf Verbindungen aufgebaut haben, die solche Parameter annehmen. Lassen Sie uns [Ihr ursprüngliches GitHub-Problem] (https://github.com/facebook/relay/issues/760) erneut öffnen und sehen, ob wir eine Lösung ausarbeiten können. – wincent

+1

Sie können vorhängen und anhängen, aber was ist mit den Artikel auf die 3. Position von oben nach unten zum Beispiel? Zum Beispiel hatten Sie eine Sache, sortiert nach Namen mit [A, B, D] und fügen Sie C hinzu? – FabioCosta

3

Ich hatte das gleiche Problem. Also entschied ich mich, ein npm Paket zu schreiben, um dieses Problem zu behandeln.

kann fast-relay-pagination NPM-Paket verwenden, zum Sortieren, rückwärts und vorwärts pagination und Filter Mongoose Modell oder MongoDB Objekt.

Dieses Paket verbessert graphql-relayverzögertes Laden von Mongoose oder MongoDB Fund und Limit verwenden. Wie Sie sicher wissen, graphql-relay'sconnectionFromArray holt alle Daten und führt das Schneiden von Daten, die für große Menge nicht effizient ist.


Sie ein Beispiel in unten sehen können:

... 
import { 
    fetchConnectionFromArray 
} from 'fast-relay-pagination' 
... 
export default{ 
    type: orderConnection.connectionType, 
    args: { 
    ...connectionArgs, 
    orderFieldName: { 
     type: GraphQLString, 
    }, 
    sortType: { 
     type: GraphQLInt, 
    }, 
    }, 
    resolve: needAdmin(async (_, args) => { 
    let orderFieldName = args.orderFieldName || '_id' 
    let sortType = args.sortType || -1 
    let after = args.after 
    let before = args.before 
    let filter = args.filter 
    let first = args.first 
    let last = args.last 
    return fetchConnectionFromArray({ 
     dataPromiseFunc: SampleModel.find.bind(SampleModel), // required 
     filter, // optional (for using filter on model collection) - for example => {username: 'test'} 
     after, //optiona 
     before, // optional 
     first, //optional 
     last, // optional 
     orderFieldName, // optional 
     sortType, // optional 
    }) 
    }), 
} 
Verwandte Themen