2013-09-27 7 views
2

Я пытаюсь удалить самую низкую цену с iPad в моей схеме. Я знаю, как его найти, используя пимонго, но я не могу его удалить. Вот моя схема:Pymongo: удалить элемент из массива

{ 
    "_id": "sjobs", 
    "items": [ 
     { 
      "type": "iPod", 
      "price": 20.00 
     }, 
     { 
      "type": "iPad", 
      "price": 399.99 
     }, 
     { 
      "type": "iPad", 
      "price": 199.99 
     }, 
     { 
      "type": "iPhone 5", 
      "price": 300.45 
     } 
    ] 
} 
{ 
    "_id": "bgates", 
    "items": [ 
     { 
      "type": "MacBook", 
      "price": 2900.99 
     }, 
     { 
      "type": "iPad", 
      "price": 399.99 
     },   
     { 
      "type": "iPhone 4", 
      "price": 100.00 
     }, 
     { 
      "type": "iPad", 
      "price": 99.99 
     } 
    ] 
} 

У меня есть цикл питона, который находит самую низкую цену продажи для IPad:

cursor = db.sales.find({'items.type': 'iPad'}).sort([('items', pymongo.DESCENDING)]) 
for doc in cursor: 
    cntr = 0 
    for item in doc['items']: 
     if item['type'] == 'iPad' and resetCntr == 0: 
      cntr = 1 
      sales.update(doc, {'$pull': {'items': {item['type']}}}) 

Это не работает. Что мне нужно сделать, чтобы удалить самую низкую цену iPad?

+0

Как общий комментарий: «не работает», как правило, недостаточно информации. –

+0

Извините. Я не получаю сообщение об ошибке. Программа успешно работает, но ничего не происходит с моей схемой. Следовательно, мой stmt: «не работает». –

+0

есть ли причина, по которой вы выполняете поиск и сортировку на python (перенося все документы) вместо того, чтобы использовать запрос агрегации, чтобы получить самую низкую цену за каждый элемент iPad в каждом документе _id, а затем выпустить обновление для каждого? –

ответ

0
{'$pull': {'items': {item['type']}}} 

Это не похоже на действительный json, не так ли?

не должно быть "sales.update (...)" be "db.sales.update (...)" в вашем примере?

, может быть, лучше иметь запрос в операции обновления:

db.sales.update({_id: doc[_id]}, ...) 

, а не весь документ.

и, наконец, тело обновление само по себе может быть

{'$pull': {'items': {type: item['type']}}} 
+1

это не js or mongo shell, а Python, поэтому продажи - его коллекция здесь (эквивалентно db.sales в оболочке). Обновление в вопросе такое же, как и вы предложили. –

2

Ваш код Python не делает то, что вы думаете, что он делает (если не будет много это вы не включили). Вам не нужно выполнять сортировку и итерацию на стороне клиента - вы должны заставить сервер выполнять работу. Запустить эту агрегацию трубопровод (я дающую синтаксис оболочки, вы можете вызвать его из Python, конечно):

> r = db.sales.aggregate({"$match" : { "items.type":"iPad"} }, 
          {"$unwind" : "$items"}, 
          {"$match" : { "items.type":"iPad"} }, 
          {"$group" : { "_id" : "$_id", 
             "lowest" : {"$min":"$items.price"}, 
             "count":{$sum:1} 
             } 
          }, 
          {"$match" : {count:{$gt:1}}} 
); 
{ 
    "result" : [ 
     { 
      "_id" : "bgates", 
      "lowest" : 99.99, 
      "count" : 2 
     }, 
     { 
      "_id" : "sjobs", 
      "lowest" : 199.99, 
      "count" : 2 
     } 
    ], 
    "ok" : 1 
} 

Теперь вы можете перебрать массив «r.results» и выполнить ваше обновление:

db.sales.update({ "_id" : r.results[0]._id }, 
       { "$pull" : { "items" : { "type" : "iPad", "price" : r.result[0].lowest}}}); 

Обратите внимание, что я включаю только записи, имеющие более одного iPad, поскольку в противном случае вы можете удалить единственную запись iPad в массиве. Если вы хотите удалить все «не самые высокие» цены, вы должны найти max и $pull все элементы $lt, что цена.

1

Отказ от ответственности: Приведенный ниже код не проверяется, так как у меня нет монго, установленного локально. Однако я беру время писать так им довольно уверенно его близко к работе

def remove_lowest_price(collection): 
    cursor = collection.find({}, {'items': 1}) 
    for doc in cursor: 
     items = doc['items'] 
     id = doc['_id'] 
     for item in items: 
      lowest_price = 100000 # a huge number 
      if item['type'] == 'i_pad' and item['price'] < lowest: 
       lowest = item['price'] 
     # lowest now contains the price of the cheapest ipad 
     collection.update(
      {'_id': id}, 
      {'$pull': {'items': {'price': lowest}}} 
     ) 

Конечно будет проблемой здесь, если другой элемент случается иметь точно такую ​​же цену, но я думаю, что это будет легко улучшить отсюда

Смежные вопросы