This is coming late, but hopefully, will aid someone else searching for this.
The only options are not to use regex (does not use indexes so, will be very slow for large datasets) or use the normal $text
search (fast indexed searching but no partial matches). There is a third option that uses a bit more index memory, but both supports partial matches and uses indexes (so it's fast).
You create your own "index" by generating an array of strings from a string field (call that name
for example) and storing the resulting array in an indexed array field (let's call that _nameSearch
). Like so
const getSearchArray: (str) => string[] = _str => {
const str = _str.toLowerCase();
const output = [];
let acc = "";
let accTotal = "";
str.split("").forEach(char => {
// Reset accumulator when space is encountered
// Otherwise, add the new phrase to the array
accTotal += char;
output.push(accTotal);
if (char === " ") {
acc = "";
} else {
acc += char;
output.push(acc);
}
});
return Array.from(new Set(output));
};
So if the name
value is "option", _nameSearch
would be ["o", "op", "opt", "opti", "option"]
You can then, index _nameSearch
. So you schema would look like this:
const schema = new Schema(
{
name: String,
_nameSearch: { type: [String], index: true },
...
}
);
Querying the name
field would be as easy as db.collection.find({ _nameSearch: SEARCH_STRING })
. And you'd be able to find partial matches and also make use of indexes (so very fast searching). You will however make use of a bit larger index for the name
field, so it's a trade-off, but a viable option to consider.