我需要查询以通过使用MongoDB匹配数组中的某些值来按文档的键值获取总数。我在下面解释我的文档和输入。
dataArr=[
{'login_id':9937229853,'location':'Delhi'},
{'login_id':9937229854,'location':'JK'}
]
我的文档如下。
反馈:
{
login_id:9937229853,
code: PTP,
remark:'Hello'
},
{
login_id:9937229853,
code: PTP,
remark:'Hii'
},
{
login_id:9937229853,
code: CB,
remark:'aaaaa'
},
{
login_id:9937229854,
code: PTP,
remark:'jjjjj'
},
{
login_id:9937229854,
code: CB,
remark:'dddd'
}
以上是我的收藏。在这里,我需要根据数组中存在的每个用户输入login_id与文档进行匹配,并且将根据文档键和值获取总计数。我的预期输出如下。我在下面解释我的代码。
for(var i=0;i<dataArr.length;i++){
var login=dataArr[i]['login_id'];
//console.log('cdocs',dataArr[i]['login_id']);
Feedback.collection.count({login_id:dataArr[i]['login_id']},function(cerr,cdocs){
console.log('cdocs',login);
if (!cerr) {
if(cdocs > 0){
// console.log('login',cdocs);
db.collection.aggregate([
{
$match: {
keywords: { $not: {$size: 0} }
}
},
{ $unwind: "$keywords" },
{
$group: {
_id: {$toLower: '$keywords'},
count: { $sum: 1 }
}
},
{
$match: {
login_id: login
}
}
])
.toArray((err,docs)=>{
if (!err) {
// console.log('count::',docs);
finalArr=docs;
}
})
}
}
})
}
var data={'status':'success','data':finalArr}
res.send(data);
我需要如下所示的预期结果。
finalArr=[
{'login_id':9937229853,'location':'Delhi','PTP':2,'CB':1,'remark':3},
{'login_id':9937229854,'location':'JK','PTP':1,'CB':1,'remark':2},
]
但是使用我的代码,我得到了空白的输出。请帮助我解决此问题。
答案 0 :(得分:0)
您可以通过单个聚合操作来完成所有这些操作。第一个管道阶段将是使用输入数组过滤集合中的文档。您可能需要将该数组仅映射到ID列表,以便使用$in
查询运算符,即
const ids = dataArr.map(({ login_id }) => login_id)
然后可以在$match
管道中用作
const match = { '$match': { 'login_in': { '$in': ids } } }
然后,下一个管道步骤将使用$group
阶段通过login_id
键将上述过滤的文档分组
const allGroup = { '$group': {
'_id': {
'login_id': '$login_id',
'code': '$code',
'remark': '$remark'
},
'count': { '$sum': 1 }
} }
另一个$group
流水线阶段,用于获取备注作为键/值文档列表
const remarksGroup = { '$group': {
'_id': {
'login_id': '$_id.login_id',
'code': '$_id.code'
},
'remarks': {
'$push': {
'k': '$_id.remark',
'v': '$count'
}
},
'count': { '$sum': 1 }
} }
获取与上面类似结构的代码计数
const codeGroup = { '$group': {
'_id': '$_id.login_id',
'codes': {
'$push': {
'k': '$_id.code',
'v': '$count'
}
},
'remarks': { '$first': '$remarks' }
} }
您将需要最后一个管道,以使用$arrayToObject
将键/值对数组转换为对象,使用$mergeObjects
将对象合并为一个对象,并使用{{3 }}:
const projections = { '$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{ 'login_id': '$_id' },
{ '$arrayToObject': '$codes' },
{ '$arrayToObject': '$remarks' }
]
}
} }
您的全部聚合流水线操作将是:
(async () => {
try {
const ids = dataArr.map(({ login_id }) => login_id)
const match = { '$match': { 'login_in': { '$in': ids } } }
const allGroup = { '$group': {
'_id': {
'login_id': '$login_id',
'code': '$code',
'remark': '$remark'
},
'count': { '$sum': 1 }
} }
const remarksGroup = { '$group': {
'_id': {
'login_id': '$_id.login_id',
'code': '$_id.code'
},
'remarks': {
'$push': {
'k': '$_id.remark',
'v': '$count'
}
},
'count': { '$sum': 1 }
} }
const codeGroup = { '$group': {
'_id': '$_id.login_id',
'codes': {
'$push': {
'k': '$_id.code',
'v': '$count'
}
},
'remarks': { '$first': '$remarks' }
} }
const projections = { '$$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{ 'login_id': '$_id' },
{ '$arrayToObject': '$codes' },
{ '$arrayToObject': '$remarks' }
]
}
} }
const result = await Feedback.aggregate([
match,
allGroup,
remarksGroup,
codeGroup,
projections
])
/* get the location key */
const data = result.map(item => {
const [{ location }, ...rest] = dataArr.filter(d => d.location_id === item.location_id)
return { location, ...item }
})
console.log(data)
res.send(data)
} catch (err) {
// handle error
}
})()