Reputation: 11
I have some issue with MongoDB and Autocomplete, I would like to do something as I do with SQL => like but on MongoDB (MongoDB 4.4 Percona version).
I got a database with 1.7m of cities and a replica set sharded.
I tried Mongo => filter.Text
but the result is not working fine but a result is really fast, example I'm looking for the city Barcelona
, when I write 'barc' I got 1 or 2 results but not Barcelona
, I need to write 'barcelona' for get Barcelona
in the autocomplete.
Then I tried with regex and this time the autocomplete is working but is really slow, like between 1 and 2 sec delay on each letter I add.
Is there a way to use filter.text working with a "startwith" like, or a regex solution but with (almost) no delay between each letter?
Upvotes: 1
Views: 653
Reputation: 5715
Your best option is to implement some form of caching. The thing is, you have a decent amount of data to go through and you can't use a text index as it doesn't support partial word search.
So, for the search solution itself, you should strive to optimize the regex as much as possible. As you're interested in the start of the string only, this should suffice:
const searchTerm = 'term';
db.collection.find({ name: {'$regex' : `^${searchTerm}`, '$options' : 'i'}});
This will perform case-insensitive search. Also, take a note of the Tarmo's comment, especially the debounce part.
You should think about diacritics as well. If you need to handle them you need to supply a collation to the search:
const searchTerm = 'term';
db.collection.find({name: {'$regex' : `^${searchTerm}`}}).collation({locale: "en", strength: 1});
By supplying a strength
of 1
, you will ignore both case-sensitivity and diacritics.
In any case, this is not a light operation, especially with such set size. In the end, like I said, if this autocompletion is invoked frequently - you should apply a caching mechanism on top(as I doubt the underlying data is changed frequently or actually at all).
Upvotes: 1