MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Oblicz wartość pominięcia dla danego rekordu dla posortowanego stronicowania

Nazywa się to „przekazywaniem stron do przodu”, które jest koncepcją, której można użyć do „wydajnego stronicowania” wyników w kierunku „do przodu” podczas korzystania z wyników „posortowanych”.

Dołączona logika JavaScript (ponieważ działa w powłoce), ale nietrudna do przetłumaczenia.

Ogólna koncepcja:

{ "_id": 1, "a": 3 },
{ "_id": 2, "a": 3 },
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }

Rozważ te „już posortowane” dokumenty (dla wygody) jako przykład wyników, które chcemy „stronicować” według „dwóch” elementów na stronie.

W pierwszej kolejności robisz coś takiego:

var lastVal = null,
    lastSeen = [];

db.collection.find().sort({ "a": -1 }).limit(2).forEach(function(doc) {
    if ( lastVal != doc.a ) {
        lastSeen = [];
    }
    lastVal = doc.a;
    lastSeen.push( doc._id );
    // do something useful with each document matched
});

Teraz te lastVal i lastSeen są czymś, co przechowujesz w czymś w rodzaju „zmiennej sesji”, do której można uzyskać dostęp przy następnym żądaniu w zakresie aplikacji internetowych lub w inny sposób podobny, jeśli nie.

Powinny jednak zawierać ostatnią wartość, według której sortowałeś i listę "unikalnych" _id wartości, które były widoczne od czasu, gdy ta wartość się nie zmieniła. Stąd:

lastVal = 3,
lastSeen = [1,2];

Chodzi o to, że gdy pojawi się żądanie "następnej strony", chcesz użyć tych zmiennych do czegoś takiego:

var lastVal = 3,
    lastSeen = [1,2];

db.collection.find({ 
    "_id": { "$nin": lastSeen }, 
    "a": { "$lte": lastVal }
}).sort({ "a": -1 }).limit(2).forEach(function(doc) {
    if ( lastVal != doc.a ) {
        lastSeen = [];
    }
    lastVal = doc.a;
    lastSeen.push( doc._id );
    // do something useful with each document matched
});

Powoduje to „wykluczenie” wszystkich wartości _id które są zapisane w lastSeen z listy wyników, a także upewnij się, że wszystkie wyniki muszą być „mniejsze lub równe” (kolejność malejąca) lastVal zapisane dla pola sortowania „a”.

Daje to dwa kolejne wyniki w kolekcji:

{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },

Ale po przetworzeniu nasze wartości wyglądają teraz tak:

lastVal = 2,
lastSeen = [4];

Więc teraz logika polega na tym, że nie musisz wykluczać drugiego _id wartości widziane wcześniej, ponieważ naprawdę szukasz tylko wartości „a”, które są „mniejsze lub równe” lastVal a ponieważ był tylko "jeden" _id wartość widziana przy tej wartości, to wyklucza tylko tę.

To oczywiście daje następną stronę na temat używania tego samego kodu, co powyżej:

{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }

Jest to najskuteczniejszy sposób na „przekazywanie strony do przodu” przez wyniki w ogóle i jest szczególnie przydatny do wydajnego stronicowania „posortowanych” wyników.

Jeśli jednak chcesz „przeskoczyć” na stronę 20 lub podobne działanie na dowolnym etapie, to nie jest dla Ciebie. Utknąłeś z tradycyjnym .skip() i .limit() podejście, aby móc to zrobić za pomocą „numeru strony”, ponieważ nie ma innego racjonalnego sposobu na „obliczenie” tego.

Wszystko zależy więc od tego, w jaki sposób Twoja aplikacja implementuje „stronicowanie” i z czym możesz żyć. .skip() i .limit() podejście cierpi na wydajność „pomijania” i można go uniknąć, stosując podejście tutaj.

Z drugiej strony, jeśli chcesz „przeskoczyć do strony”, to „pomijanie” jest jedyną realną opcją, chyba że chcesz zbudować „pamięć podręczna” wyników. Ale to zupełnie inna kwestia.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Odpowiednik procedury przechowywanej MongoDB

  2. Wydajność MongoDB przy rosnącej strukturze danych

  3. MongoDB $pow

  4. Samouczek MongoDB na rok 2022 – Dowiedz się, czym jest MongoDB?

  5. Najlepsza praktyka w utrzymywaniu sesji MGO