1

我有一个存储有关文章信息的集合。该集合用于存档目的,因此它是只读的。目前只使用了两个字段:“title”和“page_length”。因为我总是对首先获得更长的文章感兴趣,所以我有以下索引:{ title: 1, page_length: -1}。

我发现排序仍然很慢,因为集合非常大并且不适合内存。

假设我在这个集合上使用的几乎每个查询都需要排序({page_length:-1}),有没有办法简单地将记录按 page_length 降序存储在磁盘上?换句话说,有没有一种简单的方法可以让集合中的第一条记录成为最大的 page_length 值,第二条记录成为第二大,以此类推?

这样我就可以使用 limit(n) 抓取前 n 条记录,而无需运行排序。有任何想法吗?


更新更多信息:

我将其用于搜索自动完成功能,因此速度至关重要。我一直在使用的查询如下所示:

db.articles.find({"title": /^SomeKeyword/}).sort({page_length:-1})

我很高兴创建多个索引,因为插入不是问题,我只想最大化读取速度。

编辑:作为参考,我实际上能够通过使用 find().forEach() 将集合中的记录重新组织到一个新集合中。然后我搜索了集合,并在不需要任何排序的情况下抓取了前 N 个结果,效果非常好。请注意,这只有效,因为我的数据集永远不会改变。

4

2 回答 2

1

您的索引{ title: 1, page_length: -1 }不用于如下所示的查询:

db.collection.find( {} ).sort( { page_length: -1 } );

MongoDB 只能使用从左到右的复合索引,因此为了使用索引,您需要将“标题”作为查找或排序参数:

db.collection.find( { title: 'foo' } ).sort( { page_length: -1 } ); db.collection.find().sort( { title: 1, page_length: -1 } );

解释会告诉你:

db.so.find( {} ).sort( { page_length: -1 } ).explain();

{
    "cursor" : "BasicCursor",
    …

如果您将索引更改为:

db.so.ensureIndex({ page_length: -1, title: 1 } );

然后索引将用于排序,但您不能将索引用于仅进行查找title,您将需要一个额外的索引。如果您真的只对这两个字段感兴趣并确保使用覆盖索引会有所帮助。您必须拥有复合索引,{ page_length: -1, title: 1 }并且可以确保使用投影来使用它:

db.collection.find( {}, { page_length: 1, title: 1, _id: 0 } ).sort( { page_length: -1 } );

但是您无法决定或影响 MongoDB 如何在磁盘上存储内容。

于 2013-08-01T16:52:43.653 回答
0

我可以想到一个使用两个查询的解决方案。

首先,您可以进行覆盖查询以获取您关心的文档列表。其次,您可以使用检索到的文档列表和$in运算符来获得最终结果。

覆盖的查询将在内存中运行(或至少在磁盘上按顺序运行),因此它应该很快,并且$in可以利用_id索引,并且对于合理数量的文档应该是相当有效的。

于 2013-08-01T16:29:33.523 回答