我的数据格式如下:
{'user': 'A', 'books' :['One', 'Two','Three','Seven']}
{'user': 'B', 'books' :['Two', 'Four','Five']}
{'user': 'C', 'books' :['Five', 'One','Two','Nine','Ten','Twelve']}
{'user': 'D', 'books' :['One', 'Two','Six']}
用户共同拥有的书籍意味着某种形式的合作 它们之间。我的目标是找到合作的书籍数量 (或者用户如何进行某种形式的合作vs. 那些没有任何形式合作的人)
此时我确定我不能设计一个会泄露这些信息的查询,所以我想知道,这是mongdb的mapreduce可以做的吗?如果是这样怎么样?
我之前没有做过任何mapreduce,但是看一下mongodb文档中的例子,看起来有可能用mongodb做到这一点。
答案 0 :(得分:2)
始终更喜欢Aggregation Framework over map reduce。它要快得多。 你的两个问题有点不同,首先是合作的书籍:
db.books.aggregate([
{$unwind : "$books"},
{$group: { _id:"$books", count: {$sum: 1}}},
{$match: {count: {$gt: 1}}},
{$sort: {count: -1}}
])
将输出为:
{
"result" : [
{
"_id" : "Two",
"count" : 4
},
{
"_id" : "One",
"count" : 3
},
{
"_id" : "Five",
"count" : 2
}
],
"ok" : 1
}
显示不止一次使用的图书。
在书上与他人合作的用户更多参与:
db.books.aggregate([
{$unwind : "$books"},
{$group: { _id:"$books", users: {$push: "$user"},count: {$sum: 1 }}},
{$match:{count: {$gt: 1}}},
{$unwind: "$users"},
{$group: {_id: "$users", count: {$sum: 1}}},
{$sort: {count: -1}}
])
有一个结果:
{
"result" : [
{
"_id" : "C",
"count" : 3
},
{
"_id" : "A",
"count" : 2
},
{
"_id" : "D",
"count" : 2
},
{
"_id" : "B",
"count" : 2
}
],
"ok" : 1
}
因此,这为我们提供了为每个用户合作的书籍数量。 您可以使用这些更多的交替排序并使用$ project在密钥上获得更好的名称,但我认为这给出了一些如何使用聚合框架来解决这些问题的概念。
答案 1 :(得分:1)
db.books.aggregate([
{$unwind : "$books"},
{$group : {_id : "$books", count : {$sum : 1}}},
{$match : {count : {$gt : 1}}},
{$group : {_id : "total", count : {$sum : 1}}}
])
此查询计算在集合中出现多次的图书数量,如果我理解正确的话,这就是您要查找的内容。
答案 2 :(得分:1)
这看起来像是一个分组问题。
虽然可以使用mapreduce解决,但也可以使用聚合框架轻松解决:http://docs.mongodb.org/manual/aggregation/
我建议如下(如果你愿意,我可以“翻译”到pymongo):
db.collection.aggregate([
{$unwind: "$books" },
{$group: {_id:"$books", usedby: {$sum : 1} } },
{$sort: {"usedby": -1} }
])
它通过$ unwind创建用户手册对,计算每个用户使用多少用户,然后按降序排序。