我有一个包含以下数据的集合
{
id:1,
uid:'a1',
cat:'main',
subject:'Hello',
},
{
id:2,
uid:'a1',
cat:'a'
},
{
id:3,
uid:'a1',
cat:'b'
},
在上面的集合中我想搜索{ cat:'main' }
并希望获得以下结构中的记录
[{
id:1,
uid:'a1',
category:'main',
subject:'Hello',
},
{
id:2,
uid:'a1',
category:'a',
subject:'Hello'
},
{
id:3,
uid:'a1',
category:'b',
subject:'Hello'
}]
所以我正在尝试搜索subject
仅出现在类别main
中的集合,然后我必须获得与类别{{1}具有相同uid
的其他记录}}。
这是否可以使用mapReduce?
答案 0 :(得分:0)
使用聚合管道有两种方法可以做到这一点。不需要Map-reduce功能。
第一种方法基于这样的假设:类别main
的文档将始终插入到同一uid
的其他文档之前,并且总是比其他文档的id
小一些拥有相同的uid
。如果在插入文档时注意这一点,我们可以根据id
字段进行排序,并对其进行索引。
Sort
基于索引字段。Group
位于uid
字段。所以每组的第一条记录将是
main
类别记录。
Match
仅限具有main
类别记录的组。Unwind
每组中的所有记录并应用主题
第一条记录到每组中的所有记录。守则:
collection.aggregate([
{$sort:{"id":1}},
{$group:{"_id":"$uid",
"cat":{$first:"$cat"},
"subject":{$first:"$subject"},
"record":{$push:"$$ROOT"}}},
{$match:{"cat":"main"}},
{$unwind:"$record"},
{$project:{"_id":0,
"id":"$record.id",
"uid":"$_id",
"cat":"$record.cat",
"subject":"$subject"}}
],function(err,resp){
console.log(resp);
})
第二种方法是对您提供的简单示例的粗暴实现,这可能会变成较小的表现者。
需要额外的投影操作符来识别每个组的main
类别记录。我们根据这个预计的领域进行排序。剩下的逻辑是一样的。
db.collection.aggregate([
{$project:{"_id":0,
"id":1,"uid":1,"cat":1,"subject":1,
"isMainRecord":{$cond:[{$eq:["$cat","main"]},0,1]}}},
{$sort:{"isMainRecord":1}},
{$group:{"_id":"$uid",
"cat":{$first:"$cat"},"subject":{$first:"$subject"},
"record":{$push:"$$ROOT"}}},
{$match:{"cat":"main"}},
{$unwind:"$record"},
{$project:{"_id":0,"id":"$record.id",
"uid":"$_id","cat":"$record.cat","subject":"$subject"}}
],{allowDiskUse:true},function(err,resp){
console.log(resp);
})