MongoDB恢复旧查询或跳转到文档

时间:2014-08-31 20:23:17

标签: java mongodb mongodb-query mongodb-java

我正在开发一个系统,用户可以使用许多参数查询我的MongoDB数据库。当用户查询时,他们会得到20个结果。但是,用户可能希望获得额外的20个结果,然后是另一个,等等......

我编程这样一个系统时的第一直觉是使用" skip"功能,并跳过我返回给用户的结果数量;但是,问题在于,在用户运行新查询以获取新结果所花费的时间内,许多(数百或数千个)与用户查询匹配的新文档可能已添加到MongoDB中。 因此,"跳过"不会在最后一次放松的情况下恢复查询。

例如

Documents:

1,2,3,4,5,6,7,8,9,10,11,12,13,14, etc...

我们在20号文件处留下。用户的下一个查询说要跳过20.但是,已经添加了500个新文件。现在,跳过应该是520,以便获取最后一次释放的查询。但是,我目前无法跟踪自用户上次查询以来添加了多少文档。

我的下一个想法是让用户提交上次查询中收到的最后一个文档的ID,以及用户在所有查询中收到的文档总数。我会告诉MongoDB"跳过"对于用户收到的文件总数 - 1.然后我将每个文件与用户发送的文件的ID进行比较,直到我找到用户离开的位置。

示例:

public static String getDocument(String lastId, int skip, BasicDBObject query)
{
   DBCursor cursor = collection.find(query).skip(skip);
   while(cursor.hasNext())
   {
      BasicDBObject obj = (BasicDBObject) cursor.next();
      String id = obj.getString("id");
      if(id.equals(lastId))
      {
         //Then we know that here is where we left off, and to start getting new documents
      }
    }
}

如果添加了许多新文档,我认为这是低效的,并且可能会使查询时间变慢。假设这个是正确的吗?

有没有办法查询MongoDB,告诉它在给定文档ID之前跳过所有结果?如果没有,是否有处理此类问题的标准方法?我不知道该怎么做。

1 个答案:

答案 0 :(得分:2)

好问题。我不知道为什么你在这里提到了一个“聚合”,从你的例子我看到它是一个mongo常规查询,所以我假设你的问题是关于mongo查询而不是聚合框架。

为了回答你的问题(至少根据我的理解),首先我想在这里提供一些“提示和技巧”信息。

在mongo db中有更多理由避免跳过大量对象,这是因为当你使用“skip X”查询时,引擎必须遍历所有X对象(线性扫描)在到达对象X之前。 因此,如果您检索200个对象并使用skip,则获取这200个对象的时间将随着跳过值的增加而逐渐增加。

这不是mongo,btw独有的,这也发生在关系数据库中。

在这个领域使用Mongo的一种首选方法是通过您不关心的东西返回有序结果,但是在其上有索引的东西(例如_id)。

请注意,从查询中您只是迭代了整组结果,而您并不真正关心这些结果的顺序。 所以你在这种情况下可以做的是:

getNResults ordered by id (ascending)
while(shouldRetrieveMoreResults()) {
    memorize the last id in the list of retrieved results
    instead of skip, use the following query: "get 200 objects ordered by id  ascending where id > _a_memorized_id"
    memorize the last id among retrieved ids and perform the loop again and again
}

由于_id总是有一个索引,因此查询速度很快,对于大跳过值会更有效。

这是mongo db book中写的,顺便说一下:)

现在你在这里提出的是另一个问题。基本上你说你有不断变化的数据。 在这种情况下,最好的方法是在文档中添加一些“辅助”字段,这个字段总是会增加,就像时间一样,这样您就可以按时间迭代值。时间可以编入索引。所以你可能想要使用我上面描述的相同技巧,但不是按对象id使用排序,而是使用另一个索引字段的排序。

希望这有帮助