InvalidBSON 消耗游标并引发 StopIteration。如何跳过坏文件?

InvalidBSON consumes cursor and raises StopIteration. How to skip over the bad document?

我正在浏览一个集合,其中一个集合的文档中有一些错误的日期时间数据。

mongo_query = {}
mongo_projection = {"createdAt": True} # many more date columns ommitted here
mongo_cursor = collection.find(mongo_query,
                               projection=mongo_projection
                               no_cursor_timeout=True)

遍历游标文档:

for i in range(100):
    try:
        mongo_cursor.next()
    except InvalidBSON:
        pass

我希望迭代器在处理 InvalidBSON 错误后继续,但在错误之后,.__next__() 引发 StopIteration 错误并且游标中没有更多文档。

我曾尝试使用 for doc in mongo_cursor() 访问文档以及转换为列表 list(mongo_cursor()) 但一切都以类似的方式失败。

有没有办法在pymongo中跳过游标中的坏数据?或者有更好的处理方法吗?

Pymongo 在遇到无效的BSON 时会停止迭代。理想情况下,您应该清理无效记录而不是绕过它;但也许你不知道哪些是无效的?

下面的代码将作为权宜之计。与其获取完整记录,不如获取 _id,然后对记录执行 find_one();您可以将其放入 try...except 中以清除无效记录。

顺便说一句,您可以通过使用 Mongo shell 在 0001 之前添加日期来轻松地在 pymongo 中重现 InvalidBSON 错误(用于测试!!) :

db.mycollection.insertOne({'createdAt': new Date(-10000000000000)}) // valid in pymongo
db.mycollection.insertOne({'createdAt': new Date(-100000000000000)}) // **Not** valid in pymongo
db.mycollection.insertOne({'createdAt': new Date(-100000000)}) // valid in pymongo

pymongo 代码:

from pymongo import MongoClient
from pymongo.errors import InvalidBSON

db = MongoClient()['mydatabase']
collection = db['mycollection']

mongo_query = {}
mongo_date_projection = {"createdAt": True} # many more date columns ommitted here
mongo_projection = {"_id": 1} # many more date columns ommitted here
mongo_cursor = collection.find(mongo_query,
                               projection=mongo_projection,
                               no_cursor_timeout=True)

for record in mongo_cursor:
    record_id = record.get('_id')
    try:
        item = collection.find_one({'_id': record_id}, mongo_date_projection)
        print(item)
    except InvalidBSON:
        print(f'Record with id {record_id} contains invalid BSON')

给出类似的输出:

{'_id': ObjectId('5e6e1811c7c616e1ac58cbb3'), 'createdAt': datetime.datetime(1653, 2, 10, 6, 13, 20)}
Record with id 5e6e1818c7c616e1ac58cbb4 contains invalid BSON
{'_id': ObjectId('5e6e1a73c7c616e1ac58cbb5'), 'createdAt': datetime.datetime(1969, 12, 31, 23, 43, 20)}