如何在 mongoose.js 中获取最新和最旧的记录(或者只是它们之间的时间跨度)

Posted

技术标签:

【中文标题】如何在 mongoose.js 中获取最新和最旧的记录(或者只是它们之间的时间跨度)【英文标题】:How to get the latest and oldest record in mongoose.js (or just the timespan between them) 【发布时间】:2012-09-10 03:10:28 【问题描述】:

基本问题

我有一堆记录,我需要获取最新的(最近的)和最旧的(最近的)。

在谷歌搜索时,我发现this topic 在那里我看到了几个查询:

// option 1
Tweet.findOne(, [],  $orderby :  'created_at' : -1  , function(err, post) 
  console.log( post );
);
// option 2
Tweet.find(, [], sort:[['arrival',-1]], function(err, post) 
  console.log( post );
);

不幸的是,他们都出错了:

TypeError: Invalid select() argument. Must be a string or object.

链接也有这个:

Tweet.find().sort('_id','descending').limit(15).find(function(err, post) 
  console.log( post );
);

还有一个错误:

TypeError: Invalid sort() argument. Must be a string or object.

那么我怎样才能得到这些记录呢?

时间跨度

更理想的是,我只想要最旧和最新记录之间的时间差(秒?),但我不知道如何开始进行这样的查询。

这是架构:

var Tweet = new Schema(
    body: String
  , fid:  type: String, index:  unique: true  
  , username:  type: String, index: true 
  , userid: Number
  , created_at: Date
  , source: String
);

我很确定我有最新版本的 mongoDB 和 mongoose。

编辑

这是我根据 JohnnyHK 提供的答案计算时间跨度的方式:

var calcDays = function( cb ) 
  var getOldest = function( cb ) 
    Tweet.findOne(, ,  sort:  'created_at' : 1  , function(err, post) 
      cb( null, post.created_at.getTime() );
    );
  
    , getNewest = function( cb ) 
    Tweet.findOne(, ,  sort:  'created_at' : -1  , function(err, post) 
      cb( null, post.created_at.getTime() );
    );
  

  async.parallel( 
    oldest: getOldest
  , newest: getNewest
  
    , function( err, results ) 
      var days = ( results.newest - results.oldest ) / 1000 / 60 / 60 / 24;
      // days = Math.round( days );
      cb( null, days );
    
  );

【问题讨论】:

【参考方案1】:

Mongoose 3.x 抱怨您的 findOne 调用中的 [] 参数,因为选择要包含的字段的参数不再支持数组格式。

试试这个来找到最新的:

Tweet.findOne(, ,  sort:  'created_at' : -1  , function(err, post) 
  console.log( post );
);

-1 更改为 1 以查找最旧的。

但是由于您没有使用任何字段选择,因此将几个调用链接在一起会更简洁:

Tweet.findOne().sort(created_at: -1).exec(function(err, post)  ... );

甚至将字符串传递给sort

Tweet.findOne().sort('-created_at').exec(function(err, post)  ... );

【讨论】:

我不认为你可以在一个查询中做到这一点。并行查询最小值和最大值,然后在两个查询完成后计算时间跨度。看看async.parallel 干得干净利落。 我试过这个查询,但是 'created_at' : -1 或 'created_at' : 1 都返回最旧的记录,这是怎么回事?我的猫鼬 api 版本是 3.8.X 这个方法是老版本的,现在3.8 mongoose用model.findOne().sort( field: 'asc', _id: -1 ).limit(1)找最后一个条目或者model.findOne().sort( field: -_id ).limit(1) @atom2ueki - 请您将其发布为答案而不是评论。这是我个人首选的解决方案,如果您创建它,我会支持您的答案。 _id 上排序比在created_at 上排序更快(因为有索引)【参考方案2】:

对于版本 ~3.8 mongoose

查找最后一个条目

model.findOne().sort( field: 'asc', _id: -1 ).limit(1)

或使用

model.findOne().sort( field: -_id ).limit(1)

【讨论】:

limit(1) 不是多余的,因为您已经在使用 findOne() 而不是 find() -id:-1 有什么作用?【参考方案3】:

我们有一个叫做 sort 的方法,使用它我们可以获取第一个元素(旧文档),这意味着 1 用于排序字段最后一个元素(新文档),这意味着 -1 用于排序集合领域

【讨论】:

【参考方案4】:
collectionName.findOne().sort($natural: -1).limit(1).exec(function(err, res)
    if(err)
        console.log(err);
    
    else
        console.log(res);
    

这将为您提供数据库中记录的最后一个文档。只需遵循相同的概念即可。

【讨论】:

这就是我要找的。​​span> 【参考方案5】:

快速简单 - 一条线解决方案

获取10 latest documents

MySchema.find().sort( _id: -1 ).limit(10)

获取10 oldest documents

MySchema.find().sort( _id: 1 ).limit(10)

如果您想根据其他属性(即createdAt)进行排序并获取最旧或最新的。和上面的查询类似。

MySchema.find().sort( createdAt: -1 ).limit(10)  // 10 latest docs
MySchema.find().sort( createdAt: 1 ).limit(10) // 10 oldest docs

【讨论】:

我使用MySchema.find(...).sort(createdAt: -1)[0] 来获取最新的插入,并且您的查询要快得多。谢谢。 谢谢。你知道如何获取按 createdAt 排序的最后 10 条记录吗? @philosopher 我已更新答案以回答您的问题。我还没有测试过,如果它不起作用或需要改进,请告诉我。 @WasiF 我的意思是如果我想要以不变的顺序返回的文档。无论如何,我找到了解决方案,我所做的是在它们返回后使用 Lodash 的 sortBy 对它们进行排序。【参考方案6】:
await Model.find().sort($natural:-1).limit(1); //for the latest record
await Model.find().sort($natural:1).limit(1); //for the oldest record

这个对我有用。使用mongodb自然顺序https://docs.mongodb.com/manual/reference/operator/meta/natural/

【讨论】:

【参考方案7】:

这是异步的答案 - 等待

const olderDoc: any = await Model.findOne().sort( createdAt: 1 ).lean().exec()
console.log('olderDoc', olderDoc)

const newerDoc: any = await Model.findOne().sort( createdAt: -1 ).lean().exec()
console.log('newerDoc', newerDoc)

【讨论】:

【参考方案8】:

最好的方法是有一个这样的异步函数:

async function findLastElement () 
    return await Mymodel.findOne().sort('-_id');

这样可以获得最后一个元素并确保可重用性。

【讨论】:

以上是关于如何在 mongoose.js 中获取最新和最旧的记录(或者只是它们之间的时间跨度)的主要内容,如果未能解决你的问题,请参考以下文章

从最新到最旧对我的提要中的帖子进行排序(使用 Swift 和 Parse)

获取最旧的修改价格

使用 VueFire,我如何按日期降序排列我的列表(从最新到最旧)?

git stash drop 最旧的存储(比如最旧的 5 个存储)

Django在数据库中找到最旧的条目

如何从字典中删除最旧的元素?