2013-06-28 2 views
1

Я использую mongoDB (mongoHQ) в своем приложении Flask (mongoengine). У меня есть Document который выглядит следующим образом:Получение словаря внутри списка с помощью ключа в mongoDB (mongoengine)

{items: [{id: 1}, {id: 2}, {id: 3}]} 

Есть ли способ достичь, например, в dict с id: 1 в одном запросе?

В настоящее время я просматриваю список items с заявлением next(), и я надеялся на более разумное решение. Спасибо

+0

К сожалению, я удалил его. – Rohit

ответ

0

В запросе БД или инструкции python?

Использование питона:

In [21]: d = {"items": [{"id": 1}, {"id": 2}, {"id": 3}]} 

In [22]: [i for i in d["items"] if i["id"] == 1] 
Out[22]: [{'id': 1}] 

(Добавить [0] в конец списка компе только получить словарь)

Может также использовать генератор:

In [23]: (i for i in d["items"] if i["id"] == 1) 
Out[23]: <generator object <genexpr> at 0x052A1D50> 

In [24]: _.next() 
Out[24]: {'id': 1} 

Я бы лично сделайте это выше, так как мы теперь работаем над возвращенной записью из БД.

Если вы хотите извлечь поле непосредственно (при условии, что мы хотим только первый возвращенный документ, который имеет {"id":1} в нем):

In [35]: class Doc(Document): 
    ...:  items = ListField(DictField()) 
    ...:  

In [36]: newdoc = Doc(items=[{"id":1},{"id":2},{"id":3}]) 

In [37]: newdoc.save() 
Out[37]: <Doc: Doc object> 

In [38]: for document in [d for d in Doc.objects(items__id=1).first().items if d["id"]==1]: 
    ...:  print document 
    ...:  
{u'id': 1} 

Извлечение только словарь, который соответствует сложнее, так как поле является фактически список словарей. Вы не сохраняете какую-либо скорость, изменяя запрос, чтобы возвращать только часть поля, которое соответствует, поэтому вместо этого верните полное поле и из python просто возьмите бит, который вы хотите. Такая же скорость и удобство в обслуживании.

+0

Спасибо, но я имел в виду в запросе. Как я уже говорил, я могу получить то, что мне нужно, с помощью манипуляции на питоне. – Kreutzer

+0

Изменен с версией, которая извлекает совпадающие записи из db, однако сплайсирование возвращенного поля записи, чтобы просто отображать соответствующую часть, было бы медленнее делать на стороне БД, чем от python – TyrantWave

5

Я не знаком с MongoEngine, но оператор $ projection может фильтровать массив, чтобы отображать только согласованный элемент. В оболочке Монго:

> db.foo.insert({"items": [{"id": 1}, {"id": 2}, {"id": 3}]}) 
> db.foo.find({'items.id': 1}, {'items.$': true}) 
{ "_id" : ObjectId("51ce29b68b178484ff2a01ed"), "items" : [ { "id" : 1 } ] } 

Подробнее: http://docs.mongodb.org/manual/reference/projection/positional/

Кажется, в MongoEngine вы делаете:

Foo.objects(__raw__={'items.id': 1}).only('items.$') 

Подробнее: http://mongoengine-odm.readthedocs.org/en/latest/guide/querying.html#raw-queries

+0

Да, я наткнулся на это, но, к сожалению, я не мог не получишь его работать с монгогином. спасибо, хотя – Kreutzer

+0

отредактировал мой ответ –

+0

Я пробовал варианты того, что вы предлагали все утро, но безуспешно. Он выдает ошибку о '' items. $ ''Part. Если я исключу его, я просто получаю '', а то, что я действительно хочу получить, - это dict. Спасибо, хотя – Kreutzer