I am attempting to combine two regex operators when querying my MongoDB, the second of which (id) being a number field, hence the weird conversions.
Both of these work individually, and if I replace the $where
regex with a more traditional one, it also works, however when run as is, it only looks for records that match the $where
regex
this.Asset
.find(query)
.or([
{
name: { $regex: searchQuery, $options: "i" }
},
{
$where: `function() { return this.id.toString().match(${searchQuery}) != null; }`
}
])
CodePudding user response:
Did you try
this.id.toString().match(${searchQuery}) != null || this.name.match(${searchQuery})
?
CodePudding user response:
I didn't try to debug the issue with $where
because it is best to avoid using it if at all possible. The performance characteristics of using it really are not good for usage in production environments.
Instead, you can accomplish what you want via conversion operators in MongoDB directly. The $toString
operator is particularly relevant here. Assuming that searchQuery
is "123"
, one approach would be as follows:
db.collection.find({
$or: [
{
name: {
$regex: "123",
$options: "i"
}
},
{
$expr: {
$regexMatch: {
input: {
$toString: "$id"
},
regex: "123",
options: "i"
}
}
}
]
})
Playground demonstration here. Alternatively:
db.collection.aggregate([
{
$addFields: {
idConverted: {
$toString: "$id"
}
}
},
{
$match: {
$or: [
{
name: {
$regex: "123",
$options: "i"
}
},
{
idConverted: {
$regex: "123",
$options: "i"
}
}
]
}
},
{
$unset: "idConverted"
}
])
That said, even these approaches that avoid using $where
are unlikely to be performant. Queries that filter on the transformed results are unable to use indexes efficiently. You may wish to look into other text searching approaches entirely for this to be usable by a production application.