1

I'm using mongoDB. I have a collection with:

String user_name,
Integer score

I would like to make a query that gets a user_name. The query should be sorted by score which returns the range of the 50 documents which the requested user_name is one of them.

For example, if I have 110 documents with the user_name X1-X110 with the scores 1-110 respectively and the input user_name was X72 I would like to get the range: X51-X100

EDIT:

An example of 3 documents:

{ "user_name": "X1", "score": 1}
{ "user_name": "X2", "score": 2}
{ "user_name": "X3", "score": 3}

Now if I have 110 documents as described above, and I want to find X72 I want to get the following documents:

{ "user_name": "X50", "score": 50}
{ "user_name": "X51", "score": 51}
...
{ "user_name": "X100", "score": 100}

How can I do it?

Clarification: I don't have each document rank stored. What I do have is document scores, which aren't necessarily consecutive (the example is a little bit misleading). Here's a less misleading example:

{ "user_name": "X1", "score": 17}
{ "user_name": "X2", "score": 24}
{ "user_name": "X3", "score": 38}

When searching for "X72" I would like to get a slice of size 50 in which "X72" resides according to its rank. Again, the rank is not the element score, but the element index in a hypothetical array sorted by scores.

4

3 回答 3

2

查看 MongoDB 游标操作sortlimitskip。结合使用时,它们可用于获取与您的查询匹配的元素 n 到 m:

 cursor = db.collcetion.find({...}).sort({score:1}).limit(100).skip(50);

这应该按分数顺序返回文档 51 到 100。

于 2013-09-06T14:02:28.177 回答
0

当我正确理解你的时候,你想查询在另一个玩家附近得分的用户。

通过三个查询,您可以选择用户、上面的 25 个用户和下面的 25 个用户。

首先,您需要获取用户本身及其分数。

 user = db.collection.findOne({user_name: "X72"});

然后你选择得分高于他们的接下来的 25 名球员:

 cursor db.collection.find(score: { $gt:user.score}).sort(score: -1 ).limit(25);
 //... iterate cursor

然后你选择得分低于他们的接下来的 25 名球员:

 cursor db.collection.find(score: { $lt:user.score}).sort(score: 1 ).limit(25);
 //... iterate cursor
于 2013-09-06T14:07:25.793 回答
0

不幸的是,没有直接的方法可以实现您想要的。您需要在客户端进行一些处理才能确定范围。首先通过简单的 findOne / find 获取分数

db.sample.findOne({"user_name": "X72"})

接下来,使用分数值(本例中为 72),计算客户端中的范围

lower = 72/50 => lower = 1.44

提取小数点前的数字并将其设置为较低

lower = 1
upper = lower+1 => upper = 2

现在在您的客户端中将下限值和上限值乘以 50,这将为您提供以下值。

lower = 50
upper = 100

传递下限值和上限值以查找并获取所需的列表。

db.sample.find({score:{$gt:50,$lte:100}}).sort({score:1})

一个查询的部分解决方案:

我试图用一个查询来做到这一点,但不幸的是我无法完成它。我在下面提供详细信息,希望有人能够对此进行扩展并完成我开始的工作。以下是我计划的步骤:

  1. 投影文档以将所有分数除以 50 并存储在新字段 _score 中。(据我所知)
  2. 从 _score [Stuck here] 中提取小数点前的值(目前,我没有找到任何方法来做到这一点)
  3. 根据 _score 对值进行分组。(每组会给你一个名额)
  4. 查找并返回您的分数所属的组(通过在聚合管道中使用 $match )

    db.sample.aggregate([{$project:{_id:1, user_name:1,score:1,_score:{$divide:["$score",50]}}}])

我真的很想看看这是怎么做到的!!!

于 2013-09-06T17:27:54.127 回答