5

我使用 MongoDB 并且有一个包含大约 100000 个条目的集合。

这些条目包含如下数据:

{"page": "page1", "user_count": 1400}
{"page": "page2", "user_count": 1100}
{"page": "page3", "user_count": 900}
...

我想根据 user_count 输出条目的排名,例如:

#1 - page1
#2 - page2
#3 - page3
...

...到目前为止,一切都很好。如果我只输出一个排序列表,我可以简单地使用循环计数器。

但我还必须支持各种搜索查询。因此,例如,我得到 20 个结果,并想显示结果的排名。喜欢:

#432 - page1232
#32  - page223
#345 - page332
...

最好的方法是什么?我真的不想将排名存储在集合中,因为集合不断变化。我试图用我动态构建的查找字典来解决它,但它真的很慢。对于这种情况,MongoDB 是否有任何特殊功能可以提供帮助?

4

3 回答 3

2

没有一个命令可用于执行此操作,但您可以使用 count 执行此操作:

var doc = db.pages.findOne(); // Or however you get your document
var n = db.pages.find({user_count : {$gt : doc.user_count}}).count(); // This is the number of documents with a higher user_count
var ranking = n+1; // Your doc is next in a ranking

一个单独的问题是你是否应该这样做。考虑以下:

  • 你需要一个关于 user_count 的索引。你可能已经有了这个。
  • 您需要对正在显示的每条记录执行计数查询。没有办法批量处理这些。

鉴于此,与根据应用程序的 CRUD 配置文件将排名存储在集合中相比,您对性能的影响可能更大——由您决定什么是最佳选择。

于 2013-07-29T15:35:34.780 回答
2

没有简单的方法可以用MongoDB解决这个问题。如果可能的话,我建议您查看Redis及其Sorted Sets。正如文件所说:

使用 Sorted Sets,您可以: 在大型在线游戏中占据领先地位,每次提交新分数时,您都使用ZADD. 您可以使用 轻松获取排名靠前的用户ZRANGE,还可以在给定用户名的情况下使用 来返回其在列表中的排名ZRANK。使用ZRANKZRANGE一起,您可以向用户显示与给定用户相似的分数。一切都很快。

MULTI/EXEC您可以使用block轻松获取随机页面的排名。因此,我认为这是完成您的任务的最佳方法,并且比使用 MapReduce 或使用 mongodb 重新排序要快得多。

于 2013-08-05T07:12:03.423 回答
0

从 开始,它是新聚合运算符Mongo 5的完美用例:$setWindowFields

// { page: "page1", user_count: 1400 }
// { page: "page2", user_count: 1100 }
// { page: "page3", user_count: 900  }
db.test.aggregate([

  { $setWindowFields: {
    sortBy: { user_count: -1 },
    output: { rank: { $rank: {} } }
  }},
  // { page: "page1", user_count: 1400, rank: 1 }
  // { page: "page2", user_count: 1100, rank: 2 }
  // { page: "page3", user_count: 900,  rank: 3 }

  { $match: { page: "page2" } }
])
// { page: "page2", user_count: 1100, rank: 2 }

$setWindowFields阶段通过以下方式增加全球排名:

  • 按以下顺序对文档进行排序user_countsortBy: { user_count: -1 }
  • rank并在每个文档中添加字段 ( output: { rank: { $rank: {} } })
    • 这是基于排序字段的所有文档中文档的排名user_countrank: { $rank: {} }

$match阶段用于模拟您的过滤要求。

于 2021-11-27T22:09:57.890 回答