我正在使用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做这样的事情吗?
答案 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 + 1
,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);
})