Удаление элемента _id из результатов Pymongo

Я пытаюсь создать веб-службу, используя MongoDB и Flask (используя драйвер pymongo). Запрос к базе данных, конечно же, возвращает документы с включенным полем «_id». Я не хочу отправлять это клиенту, как мне его удалить?

Вот маршрут Flask:

@app.route('/theobjects')
def index():
    objects = db.collection.find()
    return str(json.dumps({'results': list(objects)}, 
        default = json_util.default,
        indent = 4))

Это возвращает:

{
"results": [
    {
        "whatever": {
            "field1": "value", 
            "field2": "value", 
        }, 
        "whatever2": {
            "field3": "value"
        },
        ...
        "_id": {
            "$oid": "..."
        }, 

    ...
    }
]}

Я думал, что это словарь, и я могу просто удалить элемент, прежде чем возвращать его:

del objects['_id']

Но это возвращает TypeError:

TypeError: 'Cursor' object does not support item deletion

Так что это не словарь, а что-то, что мне нужно перебирать с каждым результатом в виде словаря. Поэтому я пытаюсь сделать это с помощью этого кода:

for object in objects:
    del object['_id']

Каждый словарь объектов выглядит так, как мне хотелось бы, но курсор объектов пуст. Поэтому я пытаюсь создать новый словарь и после удаления _id из каждого добавить в новый словарь, который вернет Flask:

new_object = {}
for object in objects:
    for key, item in objects.items():
        if key == '_id':
            del object['_id']
            new_object.update(object)

Это просто возвращает словарь с ключами первого уровня и ничего больше.

Так что это своего рода стандартная проблема вложенных словарей, но я также шокирован тем, что MongoDB не может легко с этим справиться.

В документации MongoDB объясняется, что вы можете исключить _id с помощью

{ _id : 0 }

Но это ничего не значит с пимонго. В документации Pymongo объясняется, что вы можете перечислить поля, которые вы хотите вернуть, но «(« _id »будет всегда включаться)». Шутки в сторону? Нет никакого способа обойти это? Есть ли что-то простое и глупое, на что я здесь не обращаю внимания?


person ddw    schedule 10.09.2012    source источник
comment
Каковы ваши настоящие претензии? Ваш код для создания нового dict странный и необязательный. В чем твоя настоящая проблема?   -  person Andreas Jung    schedule 10.09.2012
comment
Моя проблема заключалась в том, что .find ({}, {'_id': False}) не исключает _id. Однако это была проблема с моим кодом, и теперь он работает. Спасибо за вашу помощь.   -  person ddw    schedule 10.09.2012
comment
«Но курсор объектов пуст»: это потому, что вы можете выполнить итерацию только один раз, поэтому вам нужно будет выполнить итерацию, получить следующий dict, удалить '_id', поместить dict в список и в конце вернуть этот список, а не объекты .   -  person Éric Araujo    schedule 28.06.2013


Ответы (3)


Чтобы исключить поле _id в поисковом запросе в pymongo, вы можете использовать:

db.collection.find({}, {'_id': False})

Документация по этому поводу несколько ошибочна, поскольку в ней говорится, что поле _id всегда включено. Но вы можете исключить это, как показано выше.

person Thomas    schedule 10.09.2012
comment
Спасибо, это правильно. Я пробовал это перед публикацией, но я предполагаю, что возникла проблема со строкой, которую я передавал в первом параметре. Я исправил это, и теперь все хорошо. - person ddw; 10.09.2012

Вышеупомянутый ответ не работает, если мы хотим определенные поля и по-прежнему игнорируем _id. В таких случаях используйте следующее:

db.collection.find({'required_column_A':1,'required_col_B':1, '_id': False})
person srikar saggurthi    schedule 03.07.2018
comment
'_id': False должен быть во втором наборе фигурных скобок, а не в первом (как в ответе Томаса). - person wordsforthewise; 06.08.2019

Вы звоните

del objects['_id']

на объект курсора!

Очевидно, что объект курсора является итерируемым по набору результатов, а не отдельным документом, которым вы можете манипулировать.

for obj in objects:
     del obj['_id']

скорее всего то, что вы хотите.

Итак, ваше утверждение совершенно неверно, как показывает следующий код:

import pymongo

c = pymongo.Connection()
db = c['mydb']
db.foo.remove({})
db.foo.save({'foo' : 42})

for row in db.foo.find():
    del row['_id']
    print row



$ bin/python foo.py 

> {u'foo': 42}
person Andreas Jung    schedule 10.09.2012
comment
Да, я тоже попробовал ваш код перед отправкой. Но как мне затем объединить эти вложенные словари в один словарь, который можно передать клиенту? Кроме того, я понял, что пытался удалить объект курсора, поэтому сказал: «Это не словарь, а что-то, что мне нужно перебирать с каждым результатом в виде словаря». Возможно, мне стоило пропустить мой процесс открытия, но я думал, что чем больше информации, тем лучше. - person ddw; 10.09.2012