Reputation: 134
How do I project only the words found in each document from any of the keywords provided? The structure of the document is as follows:
{
_id: 24752893,
dictionary: [
{
word: 'word1',
count: 2,
},
{
word: 'word2',
count: 5,
},
{
word: 'word4',
count: 1,
},
....
]
},
{
_id: 6786765789,
dictionary: [
{
word: 'word4',
count: 3,
},
{
word: 'word2',
count: 6,
},
{
word: 'word3',
count: 3,
},
{
word: 'word5',
count: 1,
},
....
]
},
........
{
_id: 76675567,
dictionary: [
{
word: 'word1',
count: 7,
},
{
word: 'word3',
count: 2,
},
....
]
}
If a list of keywords like ['word2', 'word3'] is given, and a document should be retrieved whenever any of the words in the keyword list is found in it. I have written this aggregation pipeline to get the necessary documents:
client.database.collection.aggregate([
{
'$project': {
'_id': 1,
'dictionary': {
'$filter': {
'input': '$dictionary',
'as': 'words',
'cond': {
'$in': [
'$$words.word', keywords
]
}
}
},
}
},
{
'$match': {
'dictionary': {
'$ne': []
}
}
},
,
{
'$unwind': '$dictionary'
},
{
'$group': {
'_id': '$_id',
'score': {
'$sum': '$dictionary.count'
}
}
}
])
What I want to do is instead of projecting the whole dictionary, I want to project only the matching words for each document along with its count. And of course, I want the dictionary for each document to be in separate projected documents. Is there any way to do this?
Upvotes: 1
Views: 169
Reputation: 4452
Use $filter
to filter your arrays, try this:
let keywords = ['word2', 'word3']
db.collection.aggregate([
{
$project: {
_id: 0,
dictionary: {
$filter: {
input: "$dictionary",
as: "word",
cond: {
$in: ["$$word.word", keywords]
}
}
}
}
},
{
$match: {
$expr: {
$gt: [{ $size: "$dictionary" }, 0]
}
}
}
]);
Output:
/* 1 */
{
"dictionary" : [
{
"word" : "word2",
"count" : 5
}
]
},
/* 2 */
{
"dictionary" : [
{
"word" : "word2",
"count" : 6
},
{
"word" : "word3",
"count" : 3
}
]
},
/* 3 */
{
"dictionary" : [
{
"word" : "word3",
"count" : 2
}
]
}
Upvotes: 1