按时间戳对MongoDB文档进行排序(降序)

17

我在MongoDB中有一堆文档,它们都有一个名为"timestamp"的时间戳字段,并以"1404008160"的形式存储。我想按照降序对此集合中的所有文档进行排序。我通过以下方式完成:

sort = [('timestamp', DESCENDING)]
collection.find(limit=10).sort(sort)

然而,我没有按时间戳降序排序的结果。我认为这是因为时间戳被视为int字段。有没有方法可以解决这个问题而不改变时间戳字段的数据类型?因为在这个集合中已经有很多数据了,所以不想通过导入/导出等方式进行操作。

此外,我想让mongodb负责排序的负载,而不是在Python中通过编程实现。

明确一下:时间戳并不表示文档创建的时间,它以字符串形式存储(例如“1404217646”)。

提前感谢。


我假设您已经导入了常量,否则这些常量将表示为pymongo.DESCENDING。但实际上,这只是一个常量,用于使阅读更容易的-1。作为int,它不应该有影响,因为值应该按照那种方式排序。也许这些实际上是字符串?这意味着,在您查看shell中的数据时,这些引号""是否出现? - Neil Lunn
是的 - 引号确实出现了 - 因此时间戳被存储为字符串。我正在寻找一种解决方法,而不必更改所有现有文档中该字段的数据类型。 - jisu
实际上没有绕过的方法。即使将它们作为字符串,由于这些值是按字典序排序的,所以仍然会正确排序。除非有些是数字,有些是字符串,那么这将导致问题。如果您正在寻找一种让 MongoDB “转换”值的方法,那么除了字符串 hackery 之外,不会发生任何事情,但这并不高效。您真的需要更改类型。最好的形式是 BSON 日期,它只在内部存储时间戳值,但将自动在您的程序中转换为日期。 - Neil Lunn
好的 - 我最终重建了所有文档。 - jisu
2个回答

40

假设您的时间戳表示文档创建的时间,则可以使用 _id 替代

_id 是 MongoDB 中的 ObjectId,它存储了您的时间戳。请尝试以下操作:

sort = {'_id': -1}
collection.find({}, limit=10).sort(sort)

如果您仍然想按照自定义的时间戳字段进行排序,以下内容应该有效:

sort = {'timestamp': -1}
collection.find({}, limit=10).sort(sort)
请注意,这是基于所有timestamp字段都是同一类型(stringint)的假设。

时间戳并不表示文档创建的时间 - 所以上述方法行不通。这两种解决方案不是一样的吗? - jisu
你是对的 - 已修复。第二个解决方案有效吗?如果不行,您可能需要将数据映射到相同的类型。有一个快速的方法可以做到这一点。 - Martin Konecny
第二种解决方案也不可行,因为时间戳存储为字符串。我的排序变量实现如下:[(“时间戳”,-1)]。 无论如何,我很想知道如何“将数据映射到相同的类型”。 我考虑最终的解决方案是重构文档,使得所有文档都以bson日期格式存储时间戳。 - jisu
1
根据字符串的格式,排序仍然可以工作。一个例子是,如果格式是 YYYY-MM-DD HH:MM 的变体,其中 HH 在 [00, 23] 范围内。 - Martin Konecny
我按照相同的步骤操作,但是返回了TypeError: 如果没有指定方向,则key_or_list必须是列表的实例,>>> for x in post.find(): ... print(x['timestamp']) ... Timestamp(1591790235, 1) Timestamp(1591790259, 1) Timestamp(1591790271, 1) - a zEnItH

14

您可以使用 sort( { 'timestamp': -1 } ) 对您的集合进行降序排序。您的查询将如下所示

collection.find().sort( { 'timestamp': -1 } ).limit(10)

如果您具备 SQL 知识,您可以比较以下链接中的两个查询:

http://docs.mongodb.org/manual/reference/sql-comparison/


需要注意的是,尽管这种方法可以工作,因为您只是按单个字段进行排序,但这并不是在Python中执行此操作的最佳方式,因为字典是无序的。 - Sammaye
@Sammaye,我认为集合中有多个字段,时间戳是其中一个常见字段。 - Mulagala
文档本身有多个字段,但在排序规范中,您只提供了一个字段。 - Sammaye
建议的解决方案不就是:collection.find(limit=10).sort( { 'timestamp': -1 } ) 吗? - jisu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接