代码之家  ›  专栏  ›  技术社区  ›  Lobstw

invalidson使用游标并引发StopIteration。如何跳过坏文件?

  •  0
  • Lobstw  · 技术社区  · 6 年前

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

    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
    

    .__next__() 提高 StopIteration

    我试过用 for doc in mongo_cursor() 以及转换成列表 list(mongo_cursor()) 但一切都以类似的方式失败。

    在pymongo中有没有跳过游标中坏数据的方法?还是有更好的方法处理这个问题?

    0 回复  |  直到 6 年前
        1
  •  1
  •   Belly Buster    6 年前

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

    下面的代码将作为权宜之计。与其得到完整的记录,不如只得到 _id find_one() 记录在案;你可以把这个放在 try...except

    另外,你可以很容易地在Pymango中重现一个invalidson错误(用于测试!!)在0001年之前添加一个日期 :

    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
    

    Pymango代码:

    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)}
    
    推荐文章