2014-01-29 43 views
1

我有以下格式的数据:如何找到MongoDB的集合多个occurence嵌套数据

{'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']} 

用户共同面临的书意味着某种形式的他们之间的协作 的。我的目标是找出有多少本书正在合作 (或者,或者用户可能会以某种形式进行协作,而不是以任何形式的协作形式的那些合作伙伴)

在这一点上,我确定我不能设计一个将显示此信息的查询,所以我想知道,这是mongdb的mapreduce可以做的事情吗?如果是的话如何?

我以前没有做过任何mapreduce,但是在mongodb文档中查看示例,看起来有可能使用mongodb做到这一点。

回答

2

总是比较喜欢Aggregation Framework以上的地图缩小。它快得多。 你两个问题都有点不同,首先是书籍正在合作进行:

db.books.aggregate([ 
    {$unwind : "$books"}, 
    {$group: { _id:"$books", count: {$sum: 1}}}, 
    {$match: {count: {$gt: 1}}}, 
    {$sort: {count: -1}} 
]) 
  1. 放松身心使得在对书籍
  2. 将每一个用户和书籍文档我们总结了总用户的合作
  3. 过滤掉没有超过1的计数。没有合作者。
  4. 排序相反只是为了好玩

会给输出:

{ 
    "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}} 
]) 
  1. 像以前一样放松身心的书籍阵列。
  2. 再次将书放在书上,但是这次我们将处理这些书的用户推到了一个数组中。
  3. 过滤出没有超过1的计数。没有合作者。
  4. 放松身心的用户数组,所以我们现在有多种书籍文档到用户
  5. 集团用户和总结书
  6. 排序相反只是为了好玩

有一个结果:

{ 
    "result" : [ 
      { 
        "_id" : "C", 
        "count" : 3 
      }, 
      { 
        "_id" : "A", 
        "count" : 2 
      }, 
      { 
        "_id" : "D", 
        "count" : 2 
      }, 
      { 
        "_id" : "B", 
        "count" : 2 
      } 
    ], 
    "ok" : 1 
} 

因此,这给了我们为每个用户合作的书籍数量。 你可以使用这些更多的交替排序并使用$ project来获得更好的键名,但我认为这给出了一些有关如何使用聚合框架解决这些问题的概念。

+0

感谢您的详细解答 – mike

1

它可以通过Aggregation framework

db.books.aggregate([ 
    {$unwind : "$books"}, 
    {$group : {_id : "$books", count : {$sum : 1}}}, 
    {$match : {count : {$gt : 1}}}, 
    {$group : {_id : "total", count : {$sum : 1}}} 
]) 

此查询计数中出现不止一次的集合,这是你正在寻找的,如果我理解正确的在书的数量来完成。

  1. 首先运行开卷或扩散的本本阵列
  2. 分秒必争总出场的每本图书的数字
  3. 三滤出这似乎只是一次
  4. 第四计算的那些出现书籍总数书不止一次
1

这看起来像是一个分组问题。

尽管它可以与MapReduce的解决,它也可以很容易地通过使用聚合框架来解决:http://docs.mongodb.org/manual/aggregation/

我建议类似如下(我可以“翻译”,如果你想pymongo):

db.collection.aggregate([ 
    {$unwind: "$books" }, 
    {$group: {_id:"$books", usedby: {$sum : 1} } }, 
    {$sort: {"usedby": -1} } 
]) 

它通过$ unwind创建用户对配对,给出多少用户使用每本书的计数,然后按降序对它们进行排序。

相关问题