InvalidBSON потребляет курсор и вызывает StopIteration. Как пропустить плохой документ? - PullRequest
0 голосов
/ 13 марта 2020

Я перетаскиваю коллекцию с некоторыми неверными данными даты и времени в одном из документов коллекции.

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()), но все не получается аналогичным образом.

Есть ли способ пропустить плохие данные в курсоре в pymon go? Или есть лучший способ справиться с этим?

1 Ответ

1 голос
/ 15 марта 2020

Pymon go остановит итерацию при обнаружении недействительного BSON. В идеале вы должны исправить ваши недействительные записи, а не обходить их; но, может быть, вы не знаете, какие из них недействительны?

Код ниже будет работать как пробел. Вместо того, чтобы получить полную запись, получите просто _id, затем сделайте find_one() на записи; Вы можете поместить это в try...except для гриппа sh из недействительных записей.

Кроме того, вы можете легко воспроизвести ошибку InvalidBSON в pymon go (для тестирования !!), добавив дата, предшествующая году 0001 с использованием оболочки Mon go :

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

pymon go код:

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)}
...