2012-09-10 14 views
16

Próbuję utworzyć usługę sieciową przy użyciu MongoDB i Flask (przy użyciu sterownika pymongo). Zapytanie do bazy danych zwraca oczywiście dokumenty z dołączonym polem "_id". Nie chcę wysyłać tego do klienta, więc jak mogę go usunąć?Usuwanie elementu _id z wyników Pymongo

Oto trasa Kolba:

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

ta zwraca:

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

    ... 
    } 
]} 

myślałem, że to słownikiem a może po prostu usunąć element, przed wpuszczeniem go:

del objects['_id'] 

Ale to zwraca błąd TypeError:

TypeError: 'Cursor' object does not support item deletion 

Więc to nie jest słownik, ale coś, co muszę powtórzyć z każdym wynikiem w słowniku. Więc staram się zrobić z tym kodem:

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

Każdy słownik obiekt wygląda tak bym go lubić teraz, ale kursor obiektów jest pusty. Więc staram się stworzyć nowy słownik i po usunięciu _id od siebie, należy dodać do nowego słownika, który powróci Kolba:

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

To właśnie zwraca słownika za pomocą klawiszy na pierwszym poziomie i nic więcej.

To jest typowy problem ze standardowymi zagnieżdżonymi słownikami, ale jestem także zszokowany tym, że MongoDB nie ma sposobu na łatwe rozwiązanie tego problemu.

MongoDB documentation wyjaśnia, że ​​można wykluczyć _id z

{ _id : 0 } 

jednak, że nic nie robi z pymongo. Pymongo documentation wyjaśnia, że ​​możesz wyświetlić listę pól, które chcesz odzyskać, ale "(" _id "zawsze będzie dołączone)". Poważnie? Czy nie da się tego obejść? Czy jest coś prostego i głupiego, że tu nie ma?

+0

Jakie są Twoje rzeczywiste roszczenia tutaj? Twój kod do tworzenia nowego dicta jest dziwny i niepotrzebny. Jaki jest twój prawdziwy problem? –

+0

Mój problem polegał na tym, że .find ({}, {'_id': False}) nie wykluczał _id. Jednak był to problem z moim kodem i teraz działa. Dzięki za pomoc. – ddw

+0

"ale kursor obiektów jest pusty": to dlatego, że możesz powtarzać tylko jeden raz, więc musisz wykonać iterację, uzyskać następny dyktat, usunąć "_id", umieścić dict na liście, a na końcu zwrócić tę listę, nie obiekty. –

Odpowiedz

53

Aby wykluczyć pole _id w zapytaniu znalezienia w pymongo, można użyć:

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

Dokumentacja jest nieco zwalniając na tym, ponieważ mówi, że pole _id jest zawsze uwzględniane.Ale możesz wykluczyć to, jak pokazano powyżej.

+0

Dzięki, to prawda. Próbowałem tego przed opublikowaniem, ale domyślam się, że wystąpił problem z ciągiem, który przekazywałem w pierwszym parametrze. Naprawiłem to i teraz wszystko jest dobrze. – ddw

2

Telefonujesz

del objects['_id'] 

na obiekcie kursora!

Obiekt kursora jest oczywiście możliwy do sprawdzenia nad zestawem wyników, a nie pojedynczym dokumentem, który można modyfikować za pomocą dokumentu .

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

jest prawdopodobne, co chcesz.

Więc twierdzenie jest całkowicie błędne, jak w poniższym kodzie:

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} 
+0

Tak, próbowałem twojego kodu również przed oryginalnym wysłaniem. Ale w jaki sposób połączyć te zagnieżdżone słowniki w jeden słownik, który można przekazać klientowi? Ponadto zdałem sobie sprawę, że próbowałem usunąć obiekt kursora, dlatego powiedziałem: "Więc to nie jest słownik, ale coś, co muszę powtórzyć z każdym wynikiem w słowniku." Może powinienem był pominąć proces odkrywania, ale myślałem, że im więcej informacji, tym lepiej. – ddw