【发布时间】:2013-12-15 04:32:48
【问题描述】:
我正在开发一个在 node.js 上运行的小型应用程序,它通过 Mongoose ORM 连接到 mongodb。其中一个模型是 Person 模型 模型架构:
{
id : Number,
name : String
concatVals : String
}
例子:
[
{
id : 1,
name : 'jerry'
friends : 'adam#peter#robert#steven'
},
{
id : 2,
name : 'tony'
friends : 'richard#robert#steven'
},
{
id : 3,
name : 'mike'
friends : 'henry#steven#jerry#adam#tony'
},
{
id : 4,
name : 'peter'
friends : 'jerry#bill#bobby#steven#mike#paul'
}
]
如您所见,friends 字段基本上是一个字符串,其中包含用“#”分隔的名称。朋友字段作为字符串而不是数组存在的一个重要原因。所以我们不能改变它的类型或结构。 这个“朋友列表”在真实数据库中实际上要长得多。如您所见,这些对象中的大多数都会有相交的朋友列表(steven 出现在多个文档中)。
目标: 我需要找出有效分割每个文档中的朋友字段的方法,将其转换为一个数组,并列出所有不同填充人子集的朋友。所以基本上我在询问“tony”和“mike”人员时想要得到的结果:
[
{
name : jerry,
id : 1,
friends : 'adam#peter#robert#steven'
},
{
name : tony,
id : 2,
friends : 'richard#robert#steven'
},
{
richard ...
},
{
henry ...
},
{
steven ...
},
{
robert ...
},
{
adam ...
}
] // POPULATED friends of tony and mike
问题是数据量很大,所以我想将尽可能多的计算转移到数据库端,在服务器端进行最少的数据处理。到目前为止,我的解决方案如下所示:
Person.mapReduce({
map: function() {
emit(this.name, this.friends.split('#'));
},
reduce: function(key, values) {
return values;
},
query: {
name: {
$in: ['tony', 'mike']
}
},
out: 'friends_output'
}, // at this point we have docs with friends String splitted into array
function(err, mapReduceObject) {
mapReducePipeline.aggregate(
{ $unwind: '$value'},
{
$group: {_id: '$value'} // distinct friend docs
},
{
// combining all distinct friends
$group: {
_id: null,
allValues: { $addToSet: '$_id'}
}
},
function(err, data) {
console.log(data[0].allValues)
// here I get the list of names, not populated docs
});
});
这样我就部分地实现了我的目标:我能够结交“tony”和“mike”的所有不同朋友。但我希望填充这些朋友,但我找不到在 mapreduce 期间填充它们的好方法。 当然,我可以在 function(err, data) 中进行另一个 DB 调用,并在查询中使用名称获取 Persons
...
},
function(err, data) {
Persons.find({name : data[0].allValues},
function(err, friends){
console.log(friends);
}
);
});
但在此过程中总共有 3 个 DB 调用: - 地图减少 - 聚合 - 搜索查询
最后一个 .find() 电话一直困扰着我。您是否看到任何在 mapreduce 或聚合期间/期间填充朋友的方法?如果您对我的问题有完全不同的解决方案,请分享。
【问题讨论】:
标签: node.js mongodb mongoose mapreduce aggregation-framework