2016-01-31 8 views
6

Mi chiedevo se c'è un modo per implementare l'impaginazione in C# con DocumentDB con, o senza, il loro provider Linq?Impaginazione in C# contro DocumentDB senza Skip

Scenario: Ho un'API che supporta l'impaginazione, l'utente invia nella pagina che vogliono guardare insieme ad un pageSize, come ad esempio:

public virtual async Task<HttpResponseMessage> Get(int? page = DefaultPage, int? pageSize = DefaultPageSize)

Ho quindi utilizzare tali parametri per impaginare il i dati nel livello di accesso ai dati con il seguente codice:

return query.Skip((pageNumber - 1) * pageSize).Take(pageSize);

"Qual è il problema allora", si potrebbe chiedere. Bene, questo approccio e questo codice funzionano perfettamente durante l'utilizzo di EF e SQL. Il problema è che voglio iniziare a usare DocumentDB ma la loro implementazione Linq non ha supporto per Skip. Gli unici esempi che ho visto includono l'utilizzo della parola chiave TOP o continuation tokens che non corrisponde a e che consente agli utenti di inviare un numero di pagina e un valore di pagina.

Esiste qualche implementazione che consentirà comunque ai miei utenti di fornire pageNumber e pageSize nella richiesta?

risposta

11

SKIP è un problema di prestazioni per SQL ed è ancora peggio per NoSQL a causa del loro design scalabile. Abbiamo usato la funzionalità SKIP di MongoDB e abbiamo scoperto che essenzialmente riepona la query partendo da zero eliminando tutte le righe saltate. Più avanti nella lista a cui stavamo saltando, più a lungo la query ha richiesto. Quindi, anche se aveva la funzionalità SKIP, eravamo costretti a implementare una soluzione più performante.

I product manager di DocumentDB lo capiscono e sono resistenti all'aggiunta di SKIP. Se avessero intenzione di farlo, credo che l'avrebbero fatto quando hanno aggiunto TOP.

Per DocumentDB, l'approccio più efficiente consiste nell'utilizzare il token di continuazione e memorizzare nella cache tutti i risultati in ordine fino a (e anche prevedibilmente oltre) dove desidera l'utente. I token di continuazione sopravvivono a lungo, quindi non è necessario recuperare immediatamente tutte le pagine.

+1

Ciao Larry, Grazie per la risposta, che suona come un argomento ragionevole da fare. Anche se non riesco a vedere come utilizzare i token di continuazione e il caching, i risultati saranno fattibili se i miei utenti possono inviare qualsiasi combinazione di 'page' e' pageSize'. Sì, il valore più alto della pagina è equivalente al numero di elementi nella raccolta, anche se non sarebbe "impossibile" memorizzarlo nella cache insieme a tutte le diverse combinazioni ottenute dalla combinazione 'page' e' pageSize'? Si noti che 'pageSize' può essere tutto da 1 a circa 50. –

+2

Supponiamo che l'utente abbia impostato la dimensione della pagina su 10 e che nella cache siano presenti 27 righe. Quindi, la cache ha solo un numero sufficiente di righe per pagina 1, pagina 2 e parte di pagina 3 in memoria quando l'utente richiede la pagina 7. Il codice calcolerebbe che deve avere almeno 80 righe nella cache per mostrare la pagina 7 e andrà a recuperare molte righe usando il token di continuazione dall'ultima richiesta. Se l'utente torna alla pagina 5, lo avrà già nella cache e non avrà bisogno di colpire DocumentDB. In pratica puoi ottenere 100 o anche 1000 di righe in millisecondi a due cifre. –

+0

Grazie per la spiegazione. Sembra una buona strategia, soprattutto perché è abbastanza dinamica da consentire ai miei utenti di modificare il 'pageSize' tra richieste diverse. Immagino che potresti usare la cache integrata anche nelle richieste di singole risorse, il che è bello. –

5

Sebbene questo non risponda in modo specifico alla domanda, per i futuri googler, DB documento supporta il paging tramite token di continuazione. L'ho scritto nel dettaglio here. Il codice è necessario in questo:

var endpoint = "document db url"; 
var primaryKey = "document db key"; 
var client = new DocumentClient(new Uri(endpoint), primaryKey); 
var collection = UriFactory.CreateDocumentCollectionUri("database id", "collection id"); 

var options = new FeedOptions 
{ 
    MaxItemCount = 100 // <- Page size 
}; 

var query = client.CreateDocumentQuery<Document>(collection, options).AsDocumentQuery(); 

while (query.HasMoreResults) 
{ 
    var result = await query.ExecuteNextAsync<Document>(); 

    // Process paged results 
} 
4

Mi rendo conto che la domanda ha già accettato una (e ben detto) risposta, ma dal momento che questo particolare pagina in modo è il risultato top su Google per "DocumentDB saltare" Ho pensato di condividere la mia soluzione qui, che è in realtà solo un'implementazione di ciò che Larry ha già suggerito. Ho usato i token di continuazione e il caching in Angular per trovare un meccanismo di paging decente per le query di DocumentDB. La chiave è che permetto anche l'ordinamento e il filtraggio che riduce la necessità dell'utente di passare a pagine casuali o anche all'ultima pagina dei risultati. Qui è la mia soluzione:

http://www.zoeller.us/blog/2017/7/27/paging-results-with-documentdb

+0

Ottima soluzione. Mi piacerebbe molto vederlo aggiornato per supportare la visualizzazione di tutte le pagine (salto casuale) nella navigazione anziché solo nella pagina successiva. – defines