Returning a document by its title is very useful, but what if we want to do a full text search for any blog post that contains a specific word in it? For instance, what if we wanted to have a search input that a visitor could type MongoDB into and get back a list of all the blog posts that contain that keyword in the title? To support such a feature, we can simply add a text index to our model Schema's title attribute to tell MongoDB that we want it to generate an index for our text in our post titles:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var postSchema = new Schema({
title: { type: String, index: 'text' },
content: String,
published: { type: Date, default: Date.now }
});
module.exports = mongoose.model('post', postSchema);
To add a search option to our API, let's simply add a new _search URL parameter to our URL parameter whitelist in /routes/api/posts.js:
module.exports = restFactory('posts', Posts, serialize, deserialize, function(req, res, next) {
req.query = _pick(req.query, ['_size', '_page', '_search', 'title', 'published']);
...
});
Then, we can use this URL parameter, if it exists, to append a text search query to our /posts API endpoint that requests that data from our MongoDB index:
...
list : function(req, res) {
var query = store.find();
var size = req.query._size ? parseInt(req.query._size) : 10;
var page = req.query._page ? parseInt(req.query._page) : 1;
var filters = _omit(req.query, ['_size', '_page', '_search']);
if (req.query._search) {
query.where({$text: {$search: req.query._search}});
}
query.where(filters);
query.sort({ 'published': -1 });
query.limit(size);
query.skip(size * (page - 1));
query.exec(function(error, items) {
if (error) return res.status(400).json(storeError(error));
res.json(serializer.serialize(items));
});
},
...
Now, we will send our API a search URL parameter for a keyword:
http://localhost:3000/api/posts?_search=MongoDB
We will get back a list of items from MongoDB that contain the word MongoDB in their title.