Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: ddwОтветов: 3

Я пытаюсь создать веб-службу, используя 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 "будет всегда включаться)". Шутки в сторону? Нет никакого способа обойти это? Есть ли что-то простое и глупое, на что я здесь не обращаю внимания?

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

pythonmongodbpymongo

Ответы

Ответ 1 · рейтинг 108 · Thomas

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

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

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

Ответ 2 · рейтинг 3 · srikar saggurthi

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

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

Ответ 3 · Andreas Jung

Вы звоните

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}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы