GIVEN
a searchString "*** test text before string *** john doe | test string after string"
AND
a MongoDB document:
{
"name": "John Doe",
"matchingWords": [
"john doe", "another string"
]
}
I WANT TO query for any documents that have at least 1 element in the matchingWords field (string[]) that is found in the searchString. !! The elements in matchingWords might contains spaces.
Expected result: the mongoDB document above is found because element "john doe" is found in the searchString.
Problem
The code below is only working when matchingWords elements do not contain spaces... And I cannot find a solution to fulfill my requirement. So please help me :-)
private async findByMatchingWords(searchString: string): Promise<boolean> {
if (!searchString) return false;
const lowerCaseSearchStrings: string[] = searchString.toLowerCase().split(' ');
const results = await paymentPartyModel
.find<IPaymentParty>({
matchingWords: {
$exists: true,
$not: { $size: 0 }, // Check if array exists and is not empty
$in: lowerCaseSearchStrings,
},
})
.lean();
if (!results || results.length === 0) {
return false;
} else if (results.length === 1) {
this.info = results[0];
return true;
} else {
// 2 or more matches found...
Todo('What to do when more than one payment party matches the search?');
return false;
}
}
Use $indexOfCP
to check for the existence of the matchingWords within the substring. If the matchingWord is not inside, it would return -1. $map
this result to an array of boolean from matchingWords
array. Use $anyElementTrue
to check for any words that are within the search string.
db.collection.find({
$expr: {
$anyElementTrue: {
"$let": {
"vars": {
"searchString": "*** test text before string *** john doe | test string after string"
},
"in": {
"$map": {
"input": "$matchingWords",
"as": "mw",
"in": {
"$ne": [
-1,
{
"$indexOfCP": [
"$$searchString",
"$$mw"
]
}
]
}
}
}
}
}
}
})