Fetching prev/next posts

discord user avatar
JarrodMFlesch
2 years ago
1 1

Question

Has anyone needed to fetch neighboring documents of a specific document? How have you implemented this? I think my problem is when I am querying the first / last post. If I'm on the last post, the next post should be the first post.

My attempt

I found a few people online who were using the following mongoose queries to solve this
Prev: db.posts.find({_id: {$gt: curId}}).sort({_id: 1 }).limit(1)
Next: db.posts.find({_id: {$lt: curId}}).sort({_id: 1 }).limit(1)

And I attempted to wire it up with payload, but am not sure if I am missing something?

import payload from 'payload';
import { BeforeReadHook } from 'payload/dist/collections/config/types';

export const appendPrevNextDoc: BeforeReadHook = async ({ doc, req, query }) => {
  if (req.query && req.query.appendPrevNextDoc) {
    try {
      const prev = await payload.find({
        collection: 'session',
        sort: '-_id',
        where: {
          id: {
            less_than: doc.id
          }
        }
      });
      const next = await payload.find({
        collection: 'session',
        sort: '_id',
        where: {
          id: {
            greater_than: doc.id
          }
        }
      })
      console.log({ prev, next });
    } catch (e) {
      console.log(e)
    }
  }
  return doc;
}

Other thoughts

Is it possible to access the collection slug that is calling the hook? That would allow this hook to be reusable across collection types if I could just use a variable for collection: 'session' in the find query.

Thanks!

  • Selected Answer
    discord user avatar
    jmikrut
    2 years ago

    It seems to me like your code should actually work to do what you want. Does it work, for the most part? Outside of where you're saying:

    I think my problem is when I am querying the first / last post. If I'm on the last post, the next post should be the first post.

    If it works up to that point, and say you are on the last post with no first post, you'd just need to fetch the first post and use that manually. If this does not work at all, it might be a lower level issue. I've never personally tried to sort on IDs but I will do some digging if this should work and does not.

    Is it possible to access the collection slug that is calling the hook? That would allow this hook to be reusable across collection types if I could just use a variable for collection: 'session' in the find query.

    You should extract your hook to be reusable by wrapping your hook in another function that accepts args. That function would then return your hook, with the collection name. Like:

    const pages = {
     // ...
      hooks: {
        afterRead: [
          thisHookIsReusable({ collection: 'pages' }),
        ]
      } 
    }
    1 reply
  • discord user avatar
    JarrodMFlesch
    2 years ago

    Yeah for the most part it does work, I think it's returning data, in what order that I am not entirely sure yet, gotta add more entries. I could sort on a different field in my collection too. But anyways, manually querying the edge cases prev/next sounds like the right solution.

    You should extract your hook to be reusable by wrapping your hook in another function that accepts args.
    Yep that makes sense, I just wanted to make sure there was not a way to do that already without manually passing the collection string like you are suggesting.

    Thanks!

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.