feathers-mongodb-fuzzy-search
Add $search
to mongodb service.find
, update
, patch
and remove
queries. Full-text search on documents with stemming as well as pattern matching on individual fields.
For full-text search, be sure to index your text fields, as this plugin uses mongodb $text.
For field pattern matching, mongodb $regex is used.
Install
npm install feathers-mongodb-fuzzy-search
Usage
const service = require('feathers-mongodb')
const search = require('feathers-mongodb-fuzzy-search')
app.use('/messages', service({
Model: db.collection('messages'),
whitelist: ['$text', '$search'],
}))
app.hooks({
before: {
all: [
search(),
search({
fields: ['firstName', 'lastName']
})
]
}
})
const messages = app.service('messages')
messages.Model.createIndex({ title: 'text' })
let catDocuments = await messages.find({ query: { $search: 'cat' } })
let userDocuments = await app.service('users').find({
query: {
firstName: { $search: 's' },
lastName: { $search: 'art' }
}
})
Complete example here.
REST usage
Full text search for qwerty
with mongodb $text:
curl http://localhost:3030/messages?$search=qwerty
Search for qwerty
on field firstName
with mongodb $regex:
curl http://localhost:3030/users?firstName[$search]=qwerty
Notes
Full-text search
As default "
in $search
is removed and $search
is padded with "
. E.g. some " text
becomes "some text"
. If you want to disable this behaviour and leverage the full MongoDB $text API, you can disable escaping like this:
app.hooks({
before: {
find: search({ escape: false })
}
})
RegExp field search
Remember to allow $regex
in the service:
app.use('/messages', service({
Model: db.collection('messages'),
whitelist: ['$regex'],
}))
If not, you will get the error BadRequest: Invalid query parameter $regex
on requests.
The options
object given to search(options)
supports the following:
fields
: Array of field names to allow searching in.excludedFields
: Array of field names that can't be searched. If given, any field not in array can be searched.fieldsNotEscaped
: Array of fields to be excluded from RegExp escape. As default any field not given are escaped to avoid RegExp denial of service attacks.
app.service('users').hooks({
before: {
find: search({
excludedFields: ['fullName'],
fieldsNotEscaped: ['firstName']
})
}
})
MongoDB options
You can pass MongoDB options for $text
, like $language
, $caseSensitive
and $diacriticSensitive
with your query. E.g. If you'd like to disable stemming add $language: 'none'
to your query parameters:
users.find({
query: {
$search: 'cats',
$language: 'none'
}
})
NOTE: Remeber to allow the fields in your service:
app.use('/messages', service({
Model: db.collection('messages'),
whitelist: ['$text', '$search', '$caseSensitive', '$language', '$diacriticSensitive'],
}))
Additional information
This package is tested with MongoDB version 3.2. You will probably run into problems using older versions of MongoDB, for example version 2.4 does not support $text
search.
See mongodb documentation for more details about $text
.
See mongodb documentation for more details about $regex
.
Development
npm test # runs mocha
License
MIT © 2017 Arve Seljebu / Luc Claustres