I am trying to get a number of documents depending on what query you type in.
For example I have a bunch of documents:
[
{name: 'jon', city: 'la', country: 'us'},
{name: 'foo', city: 'ca', country: 'us'},
{name: 'alf', city: 'ca', country: 'us'},
{name: 'olla', city: 'la', country: 'us'},
{name: 'prol', city: 'la', country: 'us'},
{name: 'jon', city: 'ca', country: 'us'}
]
And if I query jon la
I want {name: 'jon', city: 'la'}
as a result.
I use Mongoose and the find()
method.
I’ve tried both with regex and the text search index.
Using text:
.find({
'$text': {
$search: 'jon la'
},
})
Using regex:
.find({
'$or': [
{ name: { $regex: '^jon|^la' } },
{ city: { $regex: '^jon|^la' } },
{ country: { $regex: '^jon|^la' } }
],
})
I get these results from both approaches:
{name: 'jon', city: 'la', country: 'us'},
{name: 'olla', city: 'la', country: 'us'},
{name: 'prol', city: 'la', country: 'us'},
{name: 'jon', city: 'ca', country: 'us'}
The problem here is I never know if it should find on name or city or any other key in the object. For example the query can be jon us
then I want to get all jon in us and not all jon and all us.
How can I achieve this?
I am thinking about a option to for example
2
Answers
I solved it by nesting
$and
with$or
's with a split.Live(almost) example:
If you explicitly want documents where
name=jon
andcity=la
(or the regex of those) you just don’t use a$or
If the problem is you don’t know what is being searched for (e.g., you need to find results where >2 words are matched) things are more complicated, you’d need to use an aggregation pipeline I think.
If what you care about is finding the "best n" matches you can use the full text search scoring
More info on textScore is here: https://www.mongodb.com/docs/manual/reference/operator/query/text/