Mongodb 在mongo中,如何高效地排序和查找与查询匹配的最后一个值?

Mongodb 在mongo中,如何高效地排序和查找与查询匹配的最后一个值?,mongodb,mongoose,Mongodb,Mongoose,假设我有一些记录如下: { 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岁的最后一张(最近的)记录。为此,我可以使

假设我有一些记录如下:

{
  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];
比如说,这些收藏有数百万张唱片。我的问题是,这是最有效的方法吗?有更好的方法吗


我最担心的是,我的应用程序是否将记录加载到内存中,以便首先对它们进行排序?

请参阅有关以下内容的文档:

极限结果 可以将sort()与limit()结合使用,以返回 排序顺序的术语)k文档,其中k是指定的限制

如果MongoDB无法通过索引扫描获得排序顺序,则 MongoDB使用top-k排序算法。此算法缓冲第一个 到目前为止,由 基础索引或集合访问。如果在任何时候 这些k结果的占用空间超过32 MB,查询将 失败

确保在
年龄
上有索引。然后,当MongoDB进行排序时,它将只在内存中保留第一个
k
(在您的示例中为1)结果


不要担心,MongoDB可以处理数百万个这样的基本查询文档。只需确保指定了正确的索引。

请参阅有关以下内容的文档:

极限结果 可以将sort()与limit()结合使用,以返回 排序顺序的术语)k文档,其中k是指定的限制

如果MongoDB无法通过索引扫描获得排序顺序,则 MongoDB使用top-k排序算法。此算法缓冲第一个 到目前为止,由 基础索引或集合访问。如果在任何时候 这些k结果的占用空间超过32 MB,查询将 失败

确保在
年龄
上有索引。然后,当MongoDB进行排序时,它将只在内存中保留第一个
k
(在您的示例中为1)结果


不要担心,MongoDB可以处理数百万个这样的基本查询文档。只需确保指定了正确的索引。

您应该创建具有以下属性的索引:

  • 该指数过滤28岁以下的所有人
  • 索引按currentMeterReading进行排序
  • 这种类型的索引是部分索引。有关更多信息,请参阅和

    下面的索引应该可以做到这一点:
    
    db.users.createIndex(
    {age:-1,currentMeterReading:-1},
    {partialFilterExpression:{age:{$lt:28}
    )
    

    如果没有索引,可能需要进行完整扫描,这对性能非常不利。
    有了索引,只有您指定的列才会存储在内存中(如果可能的话),搜索它们的速度会快得多。
    请注意,在某些或所有情况下,MongoDB可能会延迟加载索引值,而不是在创建索引时加载。这是一种实现选择

    据我所知,没有办法创建只包含最后一条记录的索引

    如果你想了解数据库是如何工作的,你必须了解数据库是如何工作的。B-树是所有数据库的常见结构。

    因此,不要为每个查询创建一个索引。创建索引之前一定要进行测量,因为这可能不是必需的。

    您应该创建具有以下属性的索引:

  • 该指数过滤28岁以下的所有人
  • 索引按currentMeterReading进行排序
  • 此类索引是部分索引。有关详细信息,请参阅和

    下面的索引应该可以做到这一点:
    
    db.users.createIndex(
    {age:-1,currentMeterReading:-1},
    {partialFilterExpression:{age:{$lt:28}
    )
    

    如果没有索引,可能需要进行完整扫描,这对性能非常不利。
    有了索引,只有您指定的列才会存储在内存中(如果可能的话),搜索它们的速度会快得多。
    请注意,在某些或所有情况下,MongoDB可能会延迟加载索引值,而不是在创建索引时加载。这是一种实现选择

    据我所知,没有办法创建只包含最后一条记录的索引

    如果你想了解数据库是如何工作的,你必须了解数据库是如何工作的。B-树是所有数据库的常见结构。

    因此,不要为每个查询创建一个索引。在创建索引之前一定要进行测量,因为这可能不是必需的。

    很抱歉,我更新了示例以更好地解释这一需要。但即使在这之后,使用此索引也会创建一个永久索引,其中记录的年龄小于28岁,对吗?在搜索中,年龄值会不时更改。如果年龄teria更改您必须在不使用
    partialFilterExpression
    的情况下为整个年龄列编制索引,或者如果值中只有很少的选择,则必须创建多个索引。您也可以在MongoDB中使用TTL创建临时索引,但这是以在索引过期时重建索引为代价的。很抱歉,我更新了示例以更好地解释此需要。B但即使在这之后,使用此索引也会对年龄小于28岁的记录创建永久索引,对吗?在搜索中,年龄值会不时更改。如果年龄条件更改,则必须在不使用
    partialFilterExpression
    的情况下索引整个年龄列,或者如果val中只有很少的选项,则必须创建多个索引您也可以在MongoDB中使用TTL创建一个临时索引,但这是以在索引过期时重建索引为代价的。