A custom aggregation has been created to search for values beginning with a specified query and prioritize exact matches in the results. The field tags
is an array containing one or more strings.
results = await Post.aggregate([
// Find all tags that start with the given query
{ $match: { 'tags': new RegExp("^" + query, 'i') } },
{ $addFields: {
// Identify if there is an exact match of the query in any string value
'exactMatch': { $eq: [ '$tags', query ] },
// Check if the first 3 characters of any string value match the query
'startsWith': { $eq: [ { $substr: [ '$tags', 0, 3 ] }, query ] },
} },
// Prioritize exact matches first
{ $sort: { 'exactMatch': -1, 'startsWith': -1 } },
// Remove the added fields from results
{ $project: { 'exactMatch': 0, 'startsWith': 0 } }
])
This method works well with a single string in the tags
field, but I am facing difficulties when using an array of strings.
The issue arises from this particular line of code:
// Check if the first 3 characters of any string value match the query
'startsWith': { $eq: [ { $substr: [ '$tags', 0, 3 ] }, query ] },
Since the tags
field is an array, the $substr
function encounters an error due to its inability to convert from BSON type array to String:
MongoServerError: PlanExecutor error during aggregation :: caused by :: can't convert from BSON type array to String
How can I modify this code to target individual values within the array instead of the array itself?
(Edit) Sample data, input & expected results
When considering the following data:
[
{
title: 'Post1',
content: 'This is test post 1.',
tags: [
'post', '12345'
]
},
{
title: 'Post2',
content: 'This is test post 2.',
tags: [
'post', '789'
]
},
{
title: 'Post3',
content: 'This is test post 3.',
tags: [
'post', '123'
]
}
]
And using an input query of "123", the expected results should be as follows:
[
{
title: 'Post3',
content: 'This is test post 3.',
tags: [
'post', '123'
]
},
{
title: 'Post1',
content: 'This is test post 1.',
tags: [
'post', '12345'
]
}
]