I had been trying to write an aggregation pipeline in MongoDB which uses a lookup stage with a sub pipeline. In that pipeline, I am trying to match a field in an array in the document with an array of strings. But it seems to be not working. I get an empty result(No documents).
Following is a document from the collection called 'card':
{
"_id": "5fbff18be1157d5f8c6089f2",
"keywords": [{
"type": "topic",
"value": "benny"
}, {
"type": "tag",
"value": "bo"
}, {
"type": "tag",
"value": "bo"
}],
"name": "tasty_steel_car"}
In this, I am trying to match the field: 'value' inside the keywords with the following query:
{
'from': 'cards',
'let': {
'keywordList': '$keywords'
},
'pipeline': [
{
"$match": {
"$expr": {
$and: [
{ "$in": [ "$keywords.value", ['benny'] ] }
]
}
}
}
],
'as': 'cards'
}
What am I doing wrong here?
The following part doesn't seem to work:
{ "$in": [ "$keywords.value", ['benny'] ] }
Even the following doesn't seem to be working:
db.cards.find({
$expr: {
$in: [ "$keywords.value", ["benny"] ]
}
})
Assuming you are trying to lookup all cards
documents which contains a specific keyword you want(eg "benny" in your example"), you may try following code:
db.getCollection(<collection name>).aggregate([
{
$lookup: {
from: "card",
let: {
keywordList: "$keywords"
},
// this pipeline is used to filter only a list with the keyword
pipeline : [
{
$project : {
keywords : {
$filter: {
input: "$keywords",
as: "keyword",
cond: {
$eq : ["$$keyword.value", "benny"]
}
}
}
}
}
],
as: "filteredCardLookups"
}
},
{
$addFields : {
// this will help to filter out card collection lookup that contains no keyword
filteredCardLookups : {
$filter: {
input: "$filteredCardLookups",
as: "filteredCardLookup",
cond: {
$ne : ["$$filteredCardLookup.keywords", []]
}
}
}
}
}
]);
your final result may look like this:
{
...
"filteredCardLookups" : [
{
"_id" : "5fbff18be1157d5f8c6089f2",
"keywords" : [
{
"type" : "topic",
"value" : "benny"
}
]
}
]
...
}
2 different things to change here. According to the documentation , $in takes the foillowing arguments:
[ <expression>, <array expression> ]
So you have to switch your arguments.
Second thing is that "benny" must not be an array, because each element of 'keywords.value' will be a string.
So the good syntax of your lookup stage is
{
"$lookup": {
"from": "cards",
"let": {
"keywordList": "$keywords.value"
},
"pipeline": [
{
"$match": {
"$expr": {
$and: [
{
"$in": [
"benny",
"$keywords.value"
]
}
]
}
}
}
],
"as": "cards"
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.