I\'m trying to find (using a regexp) an array field and returns that element only
This is my data
[
{
\"_id\": \"56d6e8bbf7404bd80a017edb\",
\"nam
As per @zangw's answer,
this ISSUE-SERVER-8892, According this issue Use $regex as the expression in a $cond, the $regex could NOT be used with cond for current mongo version.
MongoDB v4.1.11 has launched new features in ISSUE-SERVER-11947, This features adds three new expressions $regexFind
, $regexFindAll
and $regexMatch
to the aggregation language.
In your example, You can use $regexMatch expression,
Model.aggregate([
{
$project: {
tags: {
$filter: {
input: "$tags",
cond: {
$regexMatch: {
input: "$$this",
regex: query
}
}
}
}
}
}
])
Playground
According this issue Use $regex as the expression in a $cond, the $regex
could NOT be used with cond
for current mongo version.
Maybe you can try this one, filter the area3
through $match
, then get all matched tags through $group
, then remove the _id
through $project
.
caseNote.aggregate([{$unwind: '$tags'},
{$match: {tags: /area3/}},
{$group: {_id: null, tags: {$push: '$tags'}}},
{$project: {tags: 1, _id: 0}}])
.exec(function(err, tags) {
if (err)
console.log(err);
else
console.log(tags);
});
Results:
{ "tags" : [ "C area3", "b_area3" ] }
This is how I solved it. If the query can be parsed to regex the projection is not added to aggregation, but happening after the db request. If the query string is normal string, the projection added.
const { query } = req; // /rea/ or 'C area3'
const convertIfRegex = string => {
const parts = string.split('/')
let regex = string;
let options = '';
if (parts.length > 1) {
regex = parts[1];
options = parts[2];
} else {
return false
}
try {
return new RegExp(regex, options);
} catch (e) {
return null
}
};
const regex = convertIfRegex(queryString);
const aggregations = [{ $match: { tags:query } }]
if (!regex) {
aggregations.push({
$project: {
tags: {$filter: {
input: 'tags',
as: 'item',
cond: {$eq: ['$$item', query]}
}}
}
})
}
let result = await caseNote.aggregate(aggregations);
if (regex) {
result = result.reduce((acc, entry) => {
const tags = entry.tags.filter(({ tag }) => (
tag.match(regex)
))
if (tags.length) return [...acc, { ...entry, tags }];
return acc;
})
}
res.json(result)