Java 使用findOne()MongoDB从集合中检索第一个文档

Java 使用findOne()MongoDB从集合中检索第一个文档,java,mongodb,Java,Mongodb,我正在创建一个java程序,将MongoDB集合作为队列处理。因此,当我退出队列时,我需要先插入的文档 为此,我有一个名为created的字段,它表示文档创建的时间戳,我最初的想法是使用aggregation$min来使用created字段查找最小的文档 然而,我突然想到为什么不在没有任何参数的情况下使用findOne()。它将始终返回集合中的第一个文档 所以我的问题是我应该这样做吗?使用findOne()并从Mongo队列中取出第一条记录是一种好方法吗?如果我这样做有什么缺点 PS:创建Mon

我正在创建一个java程序,将MongoDB集合作为队列处理。因此,当我退出队列时,我需要先插入的文档

为此,我有一个名为created的字段,它表示文档创建的时间戳,我最初的想法是使用aggregation$min来使用created字段查找最小的文档

然而,我突然想到为什么不在没有任何参数的情况下使用findOne()。它将始终返回集合中的第一个文档

所以我的问题是我应该这样做吗?使用findOne()并从Mongo队列中取出第一条记录是一种好方法吗?如果我这样做有什么缺点

PS:创建Mongo队列程序是为了在先到先服务的基础上服务设备的请求。但由于执行请求需要一些时间,设备在处理另一个请求时无法接受另一个请求。因此,为了防止请求丢失,我使用队列逐个处理请求。

返回中的元素。这不一定与插入顺序相同。它是文档在磁盘中的显示顺序。它可能看起来是按插入顺序检索的,但通过删除和插入,您将开始看到文档出现无序

确保元素始终按插入顺序显示的方法之一是使用。如果应用程序不受其限制的影响,那么这可能是使用capped集合实现队列的最简单方法

Capped集合还可以与一起使用,以便在没有可处理的项目时,从队列中检索项目的逻辑可以继续等待项目


更新:如果不能使用capped集合,则必须按_id对结果进行排序(如果它是ObjectId),或者在集合中保留基于时间戳的字段,并按该字段对结果进行排序。

有趣的是,这里有多少人的评论不正确,但您是对的,原始的
.findOne()
带有空白查询或
.findOne({})
将返回集合中的第一个文档,即“id最低的文档”

理想情况下,对于队列处理系统,您希望在执行此操作的同时删除文档。为此,Java API支持一种方法:

这样将返回集合中的第一个文档(如上所述),并将其从集合中“删除”,以便其他操作无法找到它


您可以调用
.findAndModify()
并自己交替设置所有选项,但如果您所追求的是
\u id
保证的“最早的文档优先”,那么这就是您想要的一切。

FindOne在后台存在的内部MongoDB bTree中使用
$natural
顺序返回

默认情况下,该函数不会按
\u id
排序,也不会选择最低的
\u id

如果您发现它定期返回最低的
\u id
,那是因为文档位于
$natural
索引中

获取集合的第一个文档和排序集的第一个文档是两件完全不同的事情

如果您想使用
find和modify
从文件堆中抓取一个文档,我个人建议使用乐观锁,那么您需要使用:

findAndModify({
    sort: {_id: -1},
    remove: true
})

我之所以不推荐这种方法,是因为进程崩溃或者分布式工作程序集中的服务器宕机,那么您就失去了那个数据点。相反,您需要一个临时(乐观型)锁,如果未正确处理,可以释放该锁。

您可能需要检查。做一件事的方法有n种,如果我们也从性能角度包括点,这完全取决于用例。它没有说它是第一个。@chridam
$natural
是磁盘上的订单,而不是集合中的第一个文档。第一个文档基本上是最低的
\u id
值。@user3561036您应该尝试告诉我们。@findOne总是从集合中返回一个随机文档。因此id在集合中的形式是like string+integer。身份证不是随机分配的吗?那么说它将如何以最低id返回?@StackPointer如果您坚持默认值,则不会返回。它是“单调的”,意思是“不断增加”,所以你加的每一个都比下一个大。如果您输入了其他内容,请确保将“时间戳”作为复合
\u id
值的一部分,或者使用
.findAndModify()上的“排序”选项
在另一个包含时间戳的字段上使用remove标志。考虑到findAndRemove实际上不是mongodb core中的一个命令,我通常会说,该方法没有什么特别之处,只是findandmodify上remove标志的帮助器。值得注意的是,findandmodify的工作方式会导致大量性能损失。@Sammaye这里已经提到了
.findandmodify()
。至于“性能损失”,考虑到问题中的“用例”,您如何将性能(和准确性)与单独的
.find()
.remove()
操作进行比较,这些操作涉及到对数据库的多次调用?这真是一个反问句。
findAndModify({
    sort: {_id: -1},
    remove: true
})