天道酬勤,学无止境

遍历 PyMongo 游标会抛出 InvalidBSON: year is out of range(Iterating through PyMongo cursor throws InvalidBSON: year is out of range)

问题

我正在使用 PyMongo 简单地迭代 Mongo 集合,但我在处理大型 Mongodb 日期对象时遇到了困难。

例如,如果我的集合中有一些数据,如下所示:

"bad_data" : [ 
            {
                "id" : "id01",
                "label" : "bad_data",
                "value" : "exist",
                "type" : "String",
                "lastModified" : ISODate("2018-06-01T10:04:35.000Z"),
                "expires" : Date(9223372036854775000)
            }
        ]

我会做类似的事情:

from pymongo import MongoClient, database, cursor, collection
client = MongoClient('localhost')
db = client['db1']
db.authenticate('user', 'pass', source='admin')
collection = db['collection']
for i in collection:
    # do something with i

并得到错误InvalidBSON: year 292278994 is out of range

有什么方法可以处理这个可笑的Date()对象而不会摔倒? 我意识到在 Mongodb 中进行这样的约会很疯狂,但我对此无能为力,因为这不是我的数据。

回答1

PyMongo FAQ 中有一个关于这个主题的部分:

为什么我会收到由另一种语言的驱动程序存储的 OverflowError 解码日期?

PyMongo 将 BSON 日期时间值解码为 Python 的datetime.datetime实例。 datetime.datetime实例仅限于datetime.MINYEAR (通常为 1)和datetime.MAXYEAR (通常为 9999)之间的年份。 一些 MongoDB 驱动程序(例如 PHP 驱动程序)可以存储 BSON 日期时间,其年份值远远超出datetime.datetime支持的值。

所以这里的基本约束是驱动程序为从 BSON 映射实现的datetime.datetime类型,虽然它可能是“荒谬的”,但它对于其他语言创建这样的日期值是有效的。

正如常见问题解答中所指出的,您的一般解决方法是:

  1. 处理有问题的 BSON 日期。 虽然存储有效,但它可能不是最初存储它的任何人/任何人的“真实”意图。

  2. 在您的代码中添加“日期范围”条件以过滤“超出范围”的日期:

     result = db['collection'].find({ 'expires': { '$gte': datetime.min, '$lte': datetime.max } }) for i in result: # do something with i
  3. 如果您在进一步处理中不需要数据,请省略投影中的违规日期字段:

     result = db['collection'].find({ }, projection={ 'expires': False }) for i in result: # do something with i

当然, 'expires'顾名思义,该值的原始意图是一个遥远的未来,它永远不会出现,该数据的原始作者(很可能当前代码仍在编写它)不是了解“Python”日期限制。 因此,在所有文档以及任何代码仍在编写它的地方“降低”这个数字可能是相当安全的。

回答2

我刚刚遇到了同样的问题:

正如尼尔提到的,我引用:

PyMongo 将 BSON 日期时间值解码为 Python 的 datetime.datetime 实例。 datetime.datetime 的实例是有限的

所以仔细观察我的对象后,我注意到一些日期对象是这样的: 0000:12:30T00:00:00

就我而言,最好的方法是在将文档插入集合之前设置验证,因此如果日期为 0 ,将其设置为 1970 即可解决问题

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Iterating through PyMongo cursor throws InvalidBSON: year is out of range
    I am using PyMongo to simply iterate over a Mongo collection, but I'm struggling with handling large Mongodb date objects. For example, if I have some data in a collection that looks like this: "bad_data" : [ { "id" : "id01", "label" : "bad_data", "value" : "exist", "type" : "String", "lastModified" : ISODate("2018-06-01T10:04:35.000Z"), "expires" : Date(9223372036854775000) } ] I will do something like: from pymongo import MongoClient, database, cursor, collection client = MongoClient('localhost') db = client['db1'] db.authenticate('user', 'pass', source='admin') collection = db['collection']
  • pymongo 错误:bson.errors.InvalidBSON:“utf8”编解码器无法解码位置 25 中的字节 0xa1:起始字节无效(pymongo error: bson.errors.InvalidBSON: 'utf8' codec can't decode byte 0xa1 in position 25: invalid start byte)
    问题 tasks = list(self.collection.find().sort('_id',pymongo.DESCENDING).limit(1000)) 当我使用 pymongo 解决程序时遇到了麻烦。 文件“D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\cursor.py”,第 1097 行,在下一个文件“D:\Python27\lib\”中site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\cursor.py”,第 1039 行,在 _refresh 文件“D:\Python27\lib\site-packages\pymongo-3.2.1 -py2.7-win-amd64.egg\pymongo\cursor.py”,第 903 行,在 __send_message 文件“D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64”中。 egg\pymongo\helpers.py”,第 133 行,在 _unpack_response bson.errors.InvalidBSON:'utf8' 编解码器无法解码位置 25 的字节 0xa1
  • pymongo error: bson.errors.InvalidBSON: 'utf8' codec can't decode byte 0xa1 in position 25: invalid start byte
    tasks = list(self.collection.find().sort('_id',pymongo.DESCENDING).limit(1000)) I had a trouble when i use pymongo to solve a program. File "D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\cursor.py", line 1097, in next File "D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\cursor.py", line 1039, in _refresh File "D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\cursor.py", line 903, in __send_message File "D:\Python27\lib\site-packages\pymongo-3.2.1-py2.7-win-amd64.egg\pymongo\helpers.py", line 133, in _unpack_response bson
  • JDK1.8源码(五)——java.util.ArrayList 类
    JDK1.8源码(五)——java.util.ArrayList 类  关于 JDK 的集合类的整体介绍可以看这张图,本篇博客我们不系统的介绍整个集合的构造,重点是介绍 ArrayList 类是如何实现的。1、ArrayList 定义  ArrayList 是一个用数组实现的集合,支持随机访问,元素有序且可以重复。public class ArrayListextends AbstractListimplements List, RandomAccess, Cloneable, java.io.Serializable    ①、实现 RandomAccess 接口  这是一个标记接口,一般此标记接口用于 List 实现,以表明它们支持快速(通常是恒定时间)的随机访问。该接口的主要目的是允许通用算法改变其行为,以便在应用于随机或顺序访问列表时提供良好的性能。  比如在工具类 Collections(这个工具类后面会详细讲解)中,应用二分查找方法时判断是否实现了 RandomAccess 接口:1 int binarySearch(List<? extends Comparable<? super T>> list, T key) {2 if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)3
  • JDK1.8源码解析之java.util.ArrayList 类
    关于 JDK 的集合类的整体介绍可以看下图。本篇博客我们不系统的介绍整个集合的构造,重点是介绍 ArrayList 类是如何实现的 1 ArrayList 定义 ArrayList 是一个用数组实现的集合,支持随机访问,元素有序且可以重复。 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 1.1 实现 RandomAccess 接口   这是一个标记接口,一般此标记接口用于 List实现,以表明它们支持快速(通常是恒定时间)的随机访问。该接口的主要目的是允许通用算法改变其行为,以便在应用于随机或顺序访问列表时提供良好的性能。   比如在工具类 Collections(这个工具类后面会详细讲解)中,应用二分查找方法时判断是否实现了 RandomAccess 接口: int binarySearch(List<? extends Comparable<? super T>> list, T key) { if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD) return Collections
  • JDK1.8源码(五)——java.util.ArrayList 类
    JDK1.8源码(五)——java.util.ArrayList 类   关于 JDK 的集合类的整体介绍可以看这张图,本篇博客我们不系统的介绍整个集合的构造,重点是介绍 ArrayList 类是如何实现的。 1、ArrayList 定义   ArrayList 是一个用数组实现的集合,支持随机访问,元素有序且可以重复。 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable      ①、实现 RandomAccess 接口   这是一个标记接口,一般此标记接口用于 List 实现,以表明它们支持快速(通常是恒定时间)的随机访问。该接口的主要目的是允许通用算法改变其行为,以便在应用于随机或顺序访问列表时提供良好的性能。   比如在工具类 Collections(这个工具类后面会详细讲解)中,应用二分查找方法时判断是否实现了 RandomAccess 接口: 1 int binarySearch(List<? extends Comparable<? super T>> list, T key) { 2 if (list instanceof RandomAccess || list.size()
  • Java中的fail-fast机制
    目录 1.问题由来 2.什么是fail-fast机制 3.为什么使用foreach遍历集合删除倒数第二个元素不会报错 4.如何避免出现fail-fast 1.问题由来 阿里开发规范里有一条:不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。这是为什么呢?看下面一个Demo: public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); for (String item : list) { if ("1".equals(item)) { list.remove(item); } } System.out.println(list); } 当我们使用foreach去遍历集合的同时执行remove(或者add)时,我们可以看到控制台抛出ConcurrentModificationException异常(在删除集合中倒数第二个元素的时候不会抛出此异常,这个问题先埋个坑,我们下面会解释),而我们使用迭代器去remove的时候: public static void main(String[] args) {
  • 迭代大型列表时,Python 速度很慢(Python is slow when iterating over a large list)
    问题 我目前正在使用 pyodbc 从数据库中选择一个大的行列表。 然后将结果复制到一个大列表中,然后我尝试遍历该列表。 在我放弃 python 并尝试在 C# 中创建它之前,我想知道我是否做错了什么。 clientItems.execute("Select ids from largetable where year =?", year); allIDRows = clientItemsCursor.fetchall() #takes maybe 8 seconds. for clientItemrow in allIDRows: aID = str(clientItemRow[0]) # Do something with str -- Removed because I was trying to determine what was slow count = count+1 更多信息: for 循环目前以每秒 5 次循环的速度运行,这对我来说似乎非常慢。 选择的总行数约为 489,000。 运行它的机器有很多 RAM 和 CPU。 好像只跑一两个核心,ram是1.72GB的4gb。 谁能告诉我怎么了? 脚本运行这么慢吗? 谢谢 回答1 对于 Python 本机列表,这应该不会很慢 - 但也许 ODBC 的驱动程序正在返回一个“懒惰”的对象,该对象试图变得聪明但只是变慢了。
  • 为什么 PyMongo 会抛出 AutoReconnect?(Why does PyMongo throw AutoReconnect?)
    问题 在研究我的 Python Web 应用程序的一些奇怪问题(特别是有关 MongoDB 连接的问题)时,我注意到官方 PyMongo 文档页面上的一些内容。 我的 Web 应用程序使用 Flask,但这不会影响我面临的问题。 PyMongo 驱动程序执行连接池,但它也会在连接陈旧且重新连接到期时抛出异常 ( AutoReconnect )。 它指出(关于 AutoReconnect 异常): 为了自动重新连接,您必须处理这个异常,认识到导致它的操作不一定成功。 未来的操作将尝试打开一个到数据库的新连接(并将继续引发此异常,直到建立第一个成功连接)。 我注意到这实际上经常发生(而且它似乎不是错误)。 连接在看起来像几分钟的不活动后被 MongoDB 服务器关闭,并且需要由 Web 应用程序重新创建。 我不明白为什么 PyMongo 驱动程序在重新连接时会抛出错误(驱动程序的用户需要自己处理),而不是透明地执行。 (甚至可以有一个用户可以设置的选项,以便确实抛出AutoReconnect异常,但明智的默认设置是根本不抛出这些异常,并且无缝地重新创建连接?) 我在使用其他数据库系统时从未遇到过这种行为,这就是我有点困惑的原因。 还值得一提的是,当连接到我的本地开发 MongoDB 服务器时,我的 Web 应用程序的 MongoDB 连接永远不会失败(我认为这与它是本地连接的事实有关
  • List 抛出 ConcurrentModificationException 但 set 不抛出 ConcurrentModificationException? [复制](List throws ConcurrentModificationException but set does not throws ConcurrentModificationException? [duplicate])
    问题 这个问题在这里已经有了答案: 为什么抛出 ConcurrentModificationException 以及如何调试它8 个回答 2年前关闭。 我有以下两个java类 import java.util.*; public class ArrayListTest032 { public static void main(String[] ar) { List<String> list = new ArrayList<String>(); list.add("core java"); list.add("php"); list.add("j2ee"); list.add("struts"); list.add("hibernate"); Iterator<String> itr = list.iterator(); while (itr.hasNext()) { System.out.println(itr.next()); } list.remove("php"); while (itr.hasNext()) { System.out.println(itr.next()); } } } 当我运行上面的代码时,我得到下面的输出。 core java php j2ee struts hibernate Exception in thread "main" java.util
  • pymongo 中的默认 batchSize 是多少?(what is the default batchSize in pymongo?)
    问题 我正在使用 pymongo 在一个查询中获取大约 200 万个文档,每个文档只包含三个字符串字段。 查询只是一个简单的 find(),没有任何 limit() 或 batchSize()。 在遍历游标时,我注意到脚本在处理了大约 25k 个文档后等待了大约 30~40 秒。 所以我想知道 mongo 是否会在一批中返回所有 2M 结果? pymongo 中的默认 batchSize() 是多少? 回答1 MongoDB 中的游标默认返回最多 101 个文档或足以让您达到 1 MB。 在弹出到 4MB 之后调用遍历光标。 返回的文档数量将取决于您的文档有多大: 光标批次 MongoDB 服务器批量返回查询结果。 批处理大小不会超过最大 BSON 文档大小。 对于大多数查询,第一批返回 101 个文档或刚好足以超过 1 兆字节的文档。 后续批次大小为 4 兆字节。 要覆盖批处理的默认大小,请参阅 batchSize() 和 limit()。 对于包含没有索引的排序操作的查询,服务器必须将所有文档加载到内存中才能执行排序,并将返回第一批中的所有文档。 当您遍历游标并到达返回批次的末尾时,如果有更多结果,则 cursor.next() 将执行 getmore 操作以检索下一批。 http://docs.mongodb.org/manual/core/cursors/ 您可以在光标上的
  • Pymongo 游标限制(1)返回超过 1 个结果(Pymongo cursor limit(1) returns more than 1 result)
    问题 这些都是我收藏的所有文件: { "_id" : ObjectId("5110291e6ee1c31d5b275d01"), "d" : 24, "s" : [ 1, 2, 3 ] } { "_id" : ObjectId("511029266ee1c31d5b275d02"), "d" : 24, "s" : [ 4, 5, 6 ] } { "_id" : ObjectId("5110292e6ee1c31d5b275d03"), "d" : 24, "s" : [ 7, 8 ] } 这是我要运行的查询: mongo = get_collection(self.collection_name) res = mongo.find().sort([('_id', -1)]).skip(1).limit(1) get_collection()是我制作的一个辅助方法。 遍历光标res只会生成一个文档: res = mongo.find().sort([('_id', -1)]).skip(1).limit(1) for document in res: print document > {u's': [4.0, 5.0, 6.0], u'_id': ObjectId('511029266ee1c31d5b275d02'), u'd': 24.0} 但是,使用偏移量访问 res 会为第
  • pymongo.errors.CursorNotFound:游标ID“ ...”在服务器上无效(pymongo.errors.CursorNotFound: cursor id '…' not valid at server)
    问题 我正在尝试使用以下代码获取mongo数据库中存在的一些ID: client = MongoClient('xx.xx.xx.xx', xxx) db = client.test_database db = client['...'] collection = db.test_collection collection = db["..."] for cursor in collection.find({ "$and" : [{ "followers" : { "$gt" : 2000 } }, { "followers" : { "$lt" : 3000 } }, { "list_followers" : { "$exists" : False } }] }): print cursor['screenname'] print cursor['_id']['uid'] id = cursor['_id']['uid'] 但是,过了一会儿,我收到此错误: pymongo.errors.CursorNotFound:游标ID'...'在服务器上无效。 我发现这篇文章提到了这个问题。 不过,我不清楚该采取哪种解决方案。 是否可以使用find().batch_size(30) ? 上面的命令到底是做什么的? 我可以使用batch_size获取所有数据库ID吗? 回答1
  • mongodb游标ID无效错误(mongodb cursor id not valid error)
    问题 我正在尝试遍历此循环: for doc in coll.find() 我在第100,000个以上的记录中收到以下错误。 File "build\bdist.win32\egg\pymongo\cursor.py", line 703, in next File "build\bdist.win32\egg\pymongo\cursor.py", line 679, in _refresh File "build\bdist.win32\egg\pymongo\cursor.py", line 628, in __send_message File "build\bdist.win32\egg\pymongo\helpers.py", line 95, in _unpack_response pymongo.errors.OperationFailure: cursor id '1236484850793' not valid at server 这个错误是什么意思? 回答1 也许光标在服务器上超时了。 要查看这是否是问题,请尝试将timeout = False设置为: for doc in coll.find(timeout=False) 参见http://api.mongodb.org/python/1.6/api/pymongo/collection.html
  • 如何从 mongo db 游标遍历所有其他文档(How to iterate through every other document from a mongo db cursor)
    问题 我有一个 mongo DB 游标,其中包含要创建到 Dataframes 中的文档。 然而,在光标所在的文件可以有一个runTime那是太近了。 因此,我想获取所有其他文档并从中制作一个数据框。 Attempt 1. all_df_forecast = [] for doc in cursor[::2]: single_fc_df = pd.DataFrame(doc['data']['PRICES SPOT']) all_df_forecast.append(single_fc_df) 结果: IndexError: Cursor instances do not support slice steps Attempt 2. all_df_forecast = [] for doc in range(0, cursor.count(), 2): single_fc_df = pd.DataFrame(doc['data']['PRICES SPOT']) all_df_forecast.append(single_fc_df) 结果在TypeError: 'int' object is not subscriptable 现在这就是光标与具有数据的文档的方式。 cursor = self._collection.find({ "Type": "f", "runTime":
  • 选择查询返回“零”记录时如何处理游标异常(How to handle cursor exception when the select query returns "zero" records)
    问题 选择查询返回“零”记录时如何处理游标异常 我在一个过程中有一个游标,在游标初始化后我遍历游标以访问它的数据。 但问题是当游标选择查询返回 0 条记录时,它会抛出异常 ORA-06531:对未初始化集合的引用。 如何处理这个异常? ---程序代码 create or replace PROCEDURE BIQ_SECURITY_REPORT (out_chr_err_code OUT VARCHAR2, out_chr_err_msg OUT VARCHAR2, out_security_tab OUT return_security_arr_result , ) IS l_chr_srcstage VARCHAR2 (200); lrec return_security_report; CURSOR cur_security_data IS SELECT "ID" "requestId", "ROOM" "room", "FIRST_NAME" "FIRST_NAME", "LAST_NAME" "LAST_NAME", FROM "BI_REQUEST_CATERING_ACTIVITY" ; TYPE rec_security_data IS TABLE OF cur_security_data%ROWTYPE INDEX BY PLS_INTEGER; l_cur
  • 如何使用 pymongo 获取仅包含 ObjectId 的列表?(How do I get a list of just the ObjectId's using pymongo?)
    问题 我有以下代码: client = MongoClient() data_base = client.hkpr_restore agents_collection = data_base.agents agent_ids = agents_collection.find({},{"_id":1}) 这给了我一个结果: {u'_id': ObjectId('553020a8bf2e4e7a438b46d9')} {u'_id': ObjectId('553020a8bf2e4e7a438b46da')} {u'_id': ObjectId('553020a8bf2e4e7a438b46db')} 我如何获得 ObjectId 以便我可以使用每个 ID 来搜索另一个集合? 回答1 使用不同的 In [27]: agent_ids = agents_collection.find().distinct('_id') In [28]: agent_ids Out[28]: [ObjectId('553662940acf450bef638e6d'), ObjectId('553662940acf450bef638e6e'), ObjectId('553662940acf450bef638e6f')] In [29]: agent_id2 = [str(id) for id in
  • 如何快速获取所有文档 MongoDB pymongo(How to quickly fetch all documents MongoDB pymongo)
    问题 目前我通过在 pymongo 中遍历游标来获取文档,例如: for d in db.docs.find(): mylist.append(d) 作为参考,对同一组数据(7m 记录)执行 fetchall 大约需要 20 秒,而上述方法需要几分钟。 有没有更快的方式在 mongo 中读取批量数据? 抱歉,我是 mongo 的新手,如果需要更多信息,请告诉我。 回答1 使用 $natural 排序将绕过索引并按照文档在磁盘上的存储顺序返回文档,这意味着 mongo 不必在磁盘上随机读取。 https://docs.mongodb.com/manual/reference/method/cursor.sort/#return-natural-order 如果要使用查询,性能会严重下降。 您永远不应该依赖 FIFO 排序。 Mongo 允许自己在其存储层内移动文档。 如果你不在乎顺序,那就这样吧。 此排序是内部实现功能,您不应依赖 i 中的任何特定结构 for d in db.docs.find().sort( { $natural: 1 } ): mylist.append(d) 在 python 中,您还想使用EXHAUST游标类型,它告诉 mongo 服务器流回结果,而无需等待 pymongo 驱动程序确认每个批次 https://api.mongodb.com/python
  • PyMongo 的批量写入操作功能与多处理和生成器(PyMongo’s bulk write operation features with multiprocessing and generators)
    问题 PyMongo 支持使用sDB.insert(iter_something(converted))进行批处理的生成sDB.insert(iter_something(converted)) 。 批量写入操作功能,批量执行写入操作,以减少网络往返次数并增加写入吞吐量。 以下代码似乎有效,但我不知道 PyMongo 是否仍然能够与多处理一起迭代生成器,直到它产生 1000 个文档或 16MB 数据,然后在将批处理插入 MongoDB 时暂停生成器。 #!/usr/bin/env python from __future__ import absolute_import, division, print_function from itertools import groupby from pymongo import MongoClient from multiprocessing import Process, JoinableQueue import csv # > use test # switched to db test # > db.createCollection("abc") # { "ok" : 1 } # > db.abc.find() parts = [["Test", "A", "B01", 828288, 1, 7, 'C', 5], ["Test",
  • 为什么要遍历消耗大量内存的大型Django QuerySet?(Why is iterating through a large Django QuerySet consuming massive amounts of memory?)
    问题 该表包含大约一千万行。 for event in Event.objects.all(): print event 这将导致内存使用量稳定增加到4 GB左右,这时行将快速打印。 第一行打印之前漫长的延迟使我感到惊讶–我希望它几乎可以立即打印出来。 我还尝试了Event.objects.iterator() ,其行为方式相同。 我不知道Django将什么加载到内存中或为什么这样做。 我期望Django在数据库级别遍历结果,这意味着结果将以大致恒定的速率打印(而不是经过漫长的等待一次全部打印)。 我误会了什么? (我不知道它是否相关,但是我正在使用PostgreSQL。) 回答1 Nate C距离很近,但并不完全是。 从文档中: 您可以通过以下方式评估QuerySet: 迭代。 QuerySet是可迭代的,并且在您第一次对其进行迭代时会执行其数据库查询。 例如,这将打印数据库中所有条目的标题: for e in Entry.objects.all(): print e.headline 因此,当您第一次进入该循环并获得查询集的迭代形式时,一次就可以检索一千万行。 您遇到的等待是Django加载数据库行并为每个数据库行创建对象,然后返回实际上可以迭代的内容。 然后,您将所有内容都存储在内存中,结果溢出了。 根据我对文档的阅读,iterator(