Paginację opartą na kursorze można zaimplementować przy użyciu dowolnego pola w kolekcji, które jest unikalne, możliwe do uporządkowania i niezmienne .
_id
zadowolić wszystkie wyjątkowe, możliwe do uporządkowania i niezmienne warunki. Na podstawie tego pola możemy sortować i zwracać wynik strony z _id
ostatniego dokumentu jako kursor dla kolejnych żądań.
curl https://api.mixmax.com/items?limit=2
const items = db.items.find({}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1]._id
res.json({ items, next })
gdy użytkownik chce uzyskać drugą stronę, przekazuje kursor (jak obok) na adres URL:curl https://api.mixmax.com/items?limit=2&next=590e9abd4abbf1165862d342
const items = db.items.find({
_id: { $lt: req.query.next }
}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1]._id
res.json({ items, next })
Jeśli chcemy zwrócić wyniki w innej kolejności, na przykład datę produktu, dodamy sort=launchDate
do ciągu zapytania.curl https://api.mixmax.com/items?limit=2&sort=launchDate
const items = db.items.find({}).sort({
launchDate: -1
}).limit(2);
const next = items[items.length - 1].launchDate;
res.json({ items, next })
W przypadku kolejnych żądań stronycurl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z
const items = db.items.find({
launchDate: { $lt: req.query.next }
}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1].launchDate;
res.json({ items, next });
Jeśli uruchomimy kilka pozycji tego samego dnia i o tej samej porze? Teraz nasza launchDate
pole nie jest już unikalne i nie spełnia unikalnego, uporządkowanego i niezmiennego . stan. Nie możemy go używać jako pola kursora. Ale możemy użyć dwóch pól do wygenerowania kursora. Ponieważ wiemy, że _id
pole w MongoDB zawsze spełnia powyższe trzy warunki, wiemy, że jeśli użyjemy go obok naszego launchDate
pola, połączenie dwóch pól spełniałoby wymagania i mogłoby być razem używane jako pole kursora.curl https://api.mixmax.com/items?limit=2&sort=launchDate
const items = db.items.find({}).sort({
launchDate: -1,
_id: -1 // secondary sort in case there are duplicate launchDate values
}).limit(2);
const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });
W przypadku kolejnych żądań stronycurl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z_590e9abd4abbf1165862d342
const [nextLaunchDate, nextId] = req.query.next.split(‘_’);
const items = db.items.find({
$or: [{
launchDate: { $lt: nextLaunchDate }
}, {
// If the launchDate is an exact match, we need a tiebreaker, so we use the _id field from the cursor.
launchDate: nextLaunchDate,
_id: { $lt: nextId }
}]
}).sort({
_id: -1
}).limit(2);
const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });
Referencja:https://engineering.mixmax.com/ blog/stronicowanie-api-zbudowane-w-prawo/