web-dev-qa-db-ja.com

Pymongoの結果から_id要素を削除する

MongoDBとFlask(pymongoドライバーを使用)を使用してWebサービスを作成しようとしています。データベースへのクエリを実行すると、もちろん、「_ 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)

これは、第1レベルのキーのみを含む辞書を返すだけです。

したがって、これは一種の標準的なネストされた辞書の問題ですが、MongoDBにはこれを簡単に処理する方法がないことにもショックを受けます。

MongoDBドキュメント は、_idを除外できることを説明しています

{ _id : 0 }

しかし、それはpymongoでは何もしません。 Pymongoドキュメント は、返すフィールドをリストできることを説明していますが、「(「_ id」は常に含まれます)」。マジ?これを回避する方法はありませんか?ここで見落としている単純で愚かなものはありますか?

28
ddw

Pymongoの検索クエリで_idフィールドを除外するには、次を使用できます。

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

_idフィールドは常に含まれていると記載されているため、ドキュメントはこれについて多少誤解を招く可能性があります。ただし、上記のように除外できます。

78
Thomas

特定のフィールドが必要で、_idを無視する場合、上記の回答は失敗します。このような場合は、以下を使用してください。

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

あなたが呼んでいます

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}
1
Andreas Jung