In my model db.listing
, there are two field update
and location
that are sortable:
db.listing.find().sort({ update: -1 }).limit(50);
db.listing.find({
location: {
$near: {
$maxDistance: 10000,
$geometry: {
type: 'Point',
coordinates
}
}
}
}).limit(50);
Notice user could go to the second page, so they could return an end_cursor
which is the objectId of the document.
So ideally I like to do something like:
db.listing.sort({ update: -1 }).cursor('_id').lt(end_cursor).limit(50);
db.listing.find({
location: {
$near: {
$maxDistance: 10000,
$geometry: {
type: 'Point',
coordinates
}
}
}
}).cursor('_id').lt(end_cursor).limit(50);
Is there a feature similar to where, but instead it looks for _id
as a cursor rather than using it as a second sort?
Of course, I could use skip
but it would also require me to find the position of the end_cursor
in the query...
It looks like there isn't such feature builtin for Mongoose. So here is my solution:
const getSeenIdsByEndCursor = async ({
seen_ids = [],
end_cursor,
cursor
}) => {
if (!cursor.hasNext())
return seen_ids;
const doc = cursor.next();
seen_ids.push(doc._id);
if (end_cursor === doc._id)
return seen_ids;
return await getSeenIdsByEndCursor({
seen_ids,
end_cursor,
cursor
})
}
const listByDistance = async function({
coordinates,
distance,
end_cursor
}) {
if (!Array.isArray(coordinates)) {
return;
}
if (!end_cursor) {
return await db.listing.find({
location: {
$near: {
$maxDistance: 10000,
$geometry: {
type: 'Point',
coordinates
}
}
}
}).limit(50);
}
const cursor = db.listing.find({
location: {
$near: {
$minDistance: distance,
$maxDistance: 10000,
$geometry: {
type: 'Point',
coordinates
}
}
}
}).limit(50);
const seen_ids = await getSeenIdsByEndCursors({
cursor,
end_cursor
});
return await db.listing.find({
location: {
$near: {
$minDistance: distance,
$maxDistance: 10000,
$geometry: {
type: 'Point',
coordinates
}
}
}
}).where('_id').nin(seen_ids).limit(50);
}