我们说我有一些记录如下:
{
id: 1,
age: 22,
name: 'A',
class: 'Y'
},
{
id: 2,
age: 25,
name: 'B',
class: 'D'
},
{
id: 3,
age: 30,
name: 'C',
class: 'Y'
},
{
id: 4,
age: 40,
name: 'D',
class: 'B'
}
现在我需要获得年龄小于28的最后(最近)记录。为此,我可以使用以下代码:
const firstUsersYoungerThan28 = await Users.find({
class: 'C',
age: {
$lt: 28
}
})
.sort({
age: -1
})
.limit(1)
.lean();
const firstUserYoungerThan28 = firstUsersYoungerThan28[0];
让我们说这个系列有数百万条记录。我的问题是,这是最有效的方式吗?有更好的方法吗?
我最关心的是,我的应用程序是否将记录加载到内存中以便首先对它们进行排序?
答案 0 :(得分:3)
请参阅有关cursor.sort()
的文档:
限制结果
你可以使用sort()和limit()来返回第一个(in 排序顺序的条款)k个文件,其中k是指定的限制。
如果MongoDB无法通过索引扫描获取排序顺序,那么 MongoDB使用top-k排序算法。该算法缓冲第一个 到目前为止看到的k结果(或最后,取决于排序顺序) 底层索引或集合访问。如果在任何时候记忆 这些k结果的足迹超过32兆字节,查询将会 失败。
确保您在age
上有索引。然后,当MongoDB进行排序时,它只会将第一个k
(在您的情况下,1)结果保留在内存中。
MongoDB可以为这些基本查询处理数百万个文档,不用担心。只需确保您指定了正确的索引。
答案 1 :(得分:0)
您应该使用以下属性创建索引:
此类索引是部分索引。有关详细信息,请参阅documentation about partial indexes和using indexes for sorting。
以下索引应该可以解决问题:
db.users.createIndex(
{ age: -1, currentMeterReading: -1},
{ partialFilterExpression: { age: {$lt: 28} }
)
如果没有索引,完整扫描可能会按顺序进行,这对性能非常不利 使用索引,只有您指定的列将存储在内存中(如果可能),搜索它们会快得多 请注意,MongoDB可能会在某些或所有情况下延迟加载索引的值而不是索引创建。这是一个实现选择。
据我所知,没有办法只创建一个只有最后一条记录的索引。
如果您想了解数据库的工作原理,您必须了解indexes的工作方式,特别是B-Trees。 B树是所有数据库中非常常见的结构 Indexes do have their disadvantages所以不要为每个查询创建一个。始终在创建索引之前进行测量,因为它可能没有必要。