如何在MongoDB上订购列表并为其项目添加位置?

时间:2015-05-25 04:04:30

标签: mongodb list sorting

我正在使用MongoDB创建一个排行榜系统,所以,我想知道是否可以让我在列表及其邻居中获取文档的位置。

{ "_id": null, "name": "user_341c88077d", "value": 140 },
{ "_id": null, "name": "user_6fd772cb84", "value": 160 },
{ "_id": null, "name": "user_73bdbb334f", "value": 180 },
{ "_id": null, "name": "user_e16345075c", "value": 170 },
{ "_id": null, "name": "user_5902274617", "value": 220 }

我有一个与此类似的列表,我的目标是在尝试查找{'name': "user_73bdbb334f"}

时得到类似的结果
{ "position": 3, "_id": null, "name": "user_e16345075c", "value": 170 },
{ "position": 4, "_id": null, "name": "user_73bdbb334f", "value": 180 },
{ "position": 5, "_id": null, "name": "user_5902274617", "value": 220 }

可以用MongoDB做这样的事情吗?

3 个答案:

答案 0 :(得分:1)

您无法从MongoDB获取使用position枚举的文档。这样你的手工工作就可以了。第二个问题是让邻居们。如果你事先知道所需文件的位置,比如i,那么你可以只做.skip(i - 1).limit(3),并让你的邻居把文件放在中间。了解文档位置的唯一方法是对光标进行排序,然后计算出所需文档之前出现的文档数量,这可以使用.count()来实现。但是你的问题是几个用户可能有相同的分数,因此你无法确定哪些相同的得分文件是必需的。

在这种情况下,唯一的方法是:

  • 获取所需用户的分数,说user_score
  • 然后使用{score: {$lt: user_score}}计算文档,例如less_count
  • 然后使用{score: user_score, name: {$lt: "user_xxx"}}计算文档,例如eq_count
  • 然后为邻居
  • 累积total = less_count + eq_count + 11
  • 然后获取{score:{$ lte:user_score},名称:{$ lte:“user_xxx”}}文档,按{score:1,name:1}排序,然后.skip(total -1).limit(3)

但这总共有4个查询,我认为最好采用手动方法。

所以这是我为你的目标建议的JavaScript方式片段:

range = 1;  # The range of neighbours to show from each side
currentIndex = 1;
meIndex = -1;  # The position of the required username

db.pos.find()
      .sort({value: 1})
      .map(function(doc) {
              doc.position = currentIndex;
              if (doc._id == username) {
                 meIndex = currentIndex
              } 
              currentIndex++; 
              return doc;
           }
      )
      .filter(function(el, i, arr) {
                 return (meIndex != -1 && Math.abs(meIndex - el.position) <= range)
              }
      )

首先,您枚举文档,同时找到所需文档,然后过滤掉并仅保留所需文档及其邻居。

<强>更新

顺便说一句,您不能将null作为所有文档的_id值,因为它是唯一索引。

答案 1 :(得分:0)

此链接有助于http://docs.mongodb.org/manual/tutorial/model-tree-structures/

设计文档有点像这样,

{ "_id": null, "name": "user_2", "value": 140, neighbords: {up: "user_1", down: "user_3"}, pos: 2 }

要获取文档的位置,请在其中保留变量或sort基于某个字段,并count进行<>查询。

答案 2 :(得分:0)

您可以使用forEach()游标的find()方法迭代集合,在值键上对结果进行排序,并在文档位置添加一个额外的属性,该属性保存增量的整数值循环。

首先,您可能需要考虑在值键上添加索引以获得更好的性能(如果您还没有这样做):

db.leaderboard.ensureIndex({"value": 1});

然后,以下操作会将额外的位置字段添加到您的文档中:

var index = 1;
db.leaderboard.find().sort({"value": 1}).forEach(function (doc){
    doc.position = index;
    index++;
    db.leaderboard.save(doc);
})