2
votes

I have full text search returning results from a Keystone model. The problem is that I am generating these results using model.find(). I want to paginate these results, but I can't find a way to use $text with .paginate(). Is there a way to integrate mongoose full text search with Keystone pagination, or even paginate results from model.find()?

EDIT

I have tired using keystone.list('List').paginate().find() but I receive an error: "callback is not a function." Perhaps there is something else wrong with my code:

keystone.list('Document').paginate({
  page: req.query.page || 1,
  perPage: 10,
  maxPages: 6,
})
.find(
  { $text : { $search : req.query.search } },
  { score : { $meta: "textScore" } }
)
.sort({ score : { $meta : 'textScore' } })
.exec(function(err, results) {
  locals.documents = results;
  next();
});
2
Have you tried model.paginate().find()? - Steve Holgado
I have tried model.paginate().find(), which gives an error because paginate() isn't a function of model. I have also tried paginate().model.find(), which does the same thing as if I simply called model.find(). - ttyelud
Try this: keystone.list('MyList').paginate().find() - where 'MyList' is the name of your List. - Steve Holgado
I have. I edited the original post with the error received when doing this + my code. - ttyelud
And where do you use callback? - Steve Holgado

2 Answers

2
votes

This is how I managed to do a filter. Keystone boilerplate. Below is my todo model

import keystone from 'keystone';

const { Field: { Types } } = keystone;

const Todo = new keystone.List('Todo');

Todo.add({
   title: {
   type: String, required: true, default: Date.now,
 },
 description: { type: Types.Html, wysiwyg: true },
 createdAt: { type: Date, default: Date.now },
});

Todo.relationship({ path: 'users', ref: 'User', refPath: 'todos' });
Todo.schema.index({ title: 'text' });
Todo.register();

export default Todo;

and the paginated filter

export const list = (req, res) => {
const search = new RegExp(req.query.search || '', 'i');
const query = {
  title: search,
};
Todo.paginate({
   page: req.query.page || 1,
   perPage: 5,
   maxPages: 10,
   filters: {
     $or: [query],
   },
 }).sort('-createdAt').exec((err, items) => {
 if (err) return res.status(500).json(err);

   return res.json({
     data: items,
   });
 });
};
1
votes

You can use filters like this:

keystone.list('Document').paginate({
    page: req.query.page || 1,
    perPage: 10,
    maxPages: 6,
    filters: {
        $text: {
            $search: req.query.search || ''
        },
    },
    optionalExpression: {
        score: {$meta: "textScore"}
    },
})
.sort({ score : { $meta : 'textScore' } })
.exec(function(err, results) {
    locals.documents = results;
    next();
});

paginate function will pass it into find function. See here.