web-dev-qa-db-fra.com

Supprimer les éléments _id des résultats Pymongo

J'essaie de créer un service Web en utilisant MongoDB et Flask (en utilisant le pilote pymongo). Une requête sur la base de données renvoie des documents avec le champ "_id" inclus, bien sûr. Je ne veux pas envoyer ceci au client, alors comment puis-je le supprimer?

Voici un itinéraire Flask:

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

Cela retourne:

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

    ...
    }
]}

Je pensais que c'était un dictionnaire et je pouvais simplement supprimer l'élément avant de le renvoyer:

del objects['_id']

Mais cela retourne un TypeError:

TypeError: 'Cursor' object does not support item deletion

Donc, ce n'est pas un dictionnaire, mais quelque chose que je dois parcourir avec chaque résultat sous forme de dictionnaire. Alors j'essaie de faire ça avec ce code:

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

Chaque dictionnaire d’objets ressemble à ce que je voudrais maintenant, mais le curseur d’objet est vide. J'essaie donc de créer un nouveau dictionnaire et après avoir supprimé _id de chacun, ajouter à un nouveau dictionnaire que Flask renverra:

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

Cela retourne simplement un dictionnaire avec les clés de premier niveau et rien d'autre.

C'est donc en quelque sorte un problème de dictionnaires imbriqués standard, mais je suis également choqué que MongoDB n'ait pas de moyen de gérer cela facilement.

La documentation MongoDB explique que vous pouvez exclure _id avec

{ _id : 0 }

Mais cela ne fait rien avec le pymongo. La documentation de Pymongo explique que vous pouvez répertorier les champs que vous souhaitez renvoyer, mais "(“ _id ”sera toujours inclus)". Sérieusement? N'y a-t-il pas moyen de contourner cela? Y a-t-il quelque chose de simple et de stupide que je néglige ici?

19
ddw

Pour exclure le champ _id dans une requête de recherche dans pymongo, vous pouvez utiliser:

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

La documentation est quelque peu erronée à ce sujet car il est indiqué que le champ _id est toujours inclus. Mais vous pouvez l'exclure comme indiqué ci-dessus.

67
Thomas

La réponse ci-dessus échoue si nous voulons des champs spécifiques et ignorons toujours _id. Utilisez les éléments suivants dans de tels cas:

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

Vous appelez

del objects['_id']

sur l'objet curseur!

Il est évident que l’objet curseur est un élément itérable sur le jeu de résultats et non un document unique que vous pouvez manipuler.

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

est probablement ce que vous voulez.

Votre réclamation est donc complètement fausse comme le montre le code suivant:

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