2016-01-22 8 views
5

Abbiamo un server graphql (non scritto in javascript) che serve un elenco impaginato di oggetti. Stiamo provando a conformarci alle specifiche del relè, ma abbiamo riscontrato un caso interessante che potrebbe servirci di chiarimenti.Come gestire i cursori e l'ordinamento in Relay?

In particolare: i cursori sono autorizzati a dipendere da altri input per la connessione? Simile a https://github.com/graphql/graphql-relay-js/issues/20, la nostra connessione accetta un argomento sort_key che determina l'ordinamento della lista restituita. A seconda dell'ordine di ordinamento specificato, il bordo di un oggetto può restituire valori di cursore diversi (poiché il server ha bisogno di informazioni diverse in ciascun caso per determinare l'oggetto successivo). Tuttavia, un'attenta lettura di https://facebook.github.io/relay/docs/guides-mutations.html#range-add suggerisce che ciò non è permesso; le mutazioni che restituiscono un bordo appena creato devono restituire un singolo cursore che può essere applicato universalmente a tutte le possibili liste in cui può apparire quel bordo? In che modo Facebook risolve questo problema?

risposta

2

Sì, il cursore deve contenere abbastanza informazioni in esso per consentire il recupero della pagina successiva da quel punto in poi (compresi i vincoli come l'ordinamento e il filtro), ma se/come farlo dipende da te in quanto è l'implementazione- specifica.

Come per le mutazioni, nell'implementazione getConfigs() è possibile specificare rangeBehaviors su una base per chiamata. Quindi, se si dispone di una vista ordinata, è possibile scegliere di aggiungere o anteporre a seconda dell'ordine. Questo comportamento specifica cosa farà Relay sul lato client per aggiornare il suo archivio. È comunque responsabilità dell'utente assicurarsi che il codice del server GraphQL riceva tutte le informazioni necessarie (tramite variabili di input) per eseguire correttamente la mutazione effettiva.

+3

Non credo che ho spiegato la mia preoccupazione correttamente, ecco un esempio più concreto: si dispone di due viste della stessa lista relè-impaginato, ordinati per campi diversi. Lo stesso oggetto appare su entrambi gli elenchi, ma con cursori diversi. Hai una mutazione per creare un oggetto, con un 'RANGE_ADD' che specifica comportamenti diversi per le due viste. La mutazione sul lato server deve restituire un singolo cursore nella risposta; quale dei due cursori restituisce, e cosa fa l'altra vista visto che non ha un cursore? – Evan

+0

Buon punto. È possibile che non ci siamo imbattuti in questo internamente perché non abbiamo ancora costruito mutazioni sulle connessioni che utilizzano questo tipo di parametro. Riapre nuovamente [il tuo problema originale su GitHub] (https://github.com/facebook/relay/issues/760) di nuovo e vediamo se possiamo elaborare una soluzione. – wincent

+1

Puoi anteporre e aggiungere ma per esempio, mettere l'elemento in terza posizione dall'alto verso il basso? Ad esempio hai una cosa ordinata per nome con [A, B, D] e aggiungi C? – FabioCosta

3

Ho avuto lo stesso problema. Così, ho deciso di scrivere un pacchetto npm per gestire questo problema.

È possibile utilizzare fast-relay-pagination pacchetto NPM per l'ordinamento, avanti e indietro pagination e filtrare Mongoose modello o MongoDB oggetti.

Questo pacchetto migliora graphql-relaylazy loading utilizzando Mongoose o MongoDB scoperta e limite. Come sicuramente sai, graphql-relay'sconnectionFromArray recupera tutti i dati ed esegue l'analisi dei dati, che non è efficiente per grandi quantità.


Si può vedere un esempio in seguito:

... 
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 
    }) 
    }), 
}