2013-09-27 141 views
2

我試圖從我的模式中的iPad中刪除最低價格。我知道如何使用pymongo來查找它,但我不知道如何刪除它。 這裏是我的架構: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 
     } 
    ] 
} 

我有一個Python循環,找到最低的銷售價格爲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

對不起。我沒有收到錯誤消息。程序成功運行,但我的模式沒有任何反應。因此,我的立場是:「不起作用」。 –

+0

是否有一個原因,你正在做python搜索和排序(帶來所有的文件),而不是使用聚合查詢獲得每個文檔_id中每個iPad項目的最低價格,然後爲每個文檔發佈更新? –

回答

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

這看起來不像是有效的json,是嗎?

在你的例子中不應該是「sales.update(...)」是「db.sales.update(...)」嗎?

也許是更好地在更新操作查詢:

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

,而不是整個文檔。

最後更新體本身可能

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

這不是js也不是mongo shell,而是Python,所以銷售額是他在這裏的集合(相當於shell中的db.sales)。問題的更新與您的建議相同。 –

2

Python代碼是沒有做什麼你覺得它在做什麼(除非你不包括它的很多)。您不需要在客戶端進行排序和迭代 - 您應該讓服務器完成工作。運行此聚集管道(我給shell語法,你可以從你的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記錄。如果你想刪除所有「非最高」的價格,那麼你會想要找到最大和$lt所有元素的價格。

1

聲明:以下代碼未經測試,因爲我沒有在本地安裝mongo。但是我在這裏把我的時間寫它,以便即時通訊非常有信心,其靠近工作

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}}} 
     ) 

當然會有一個問題,如果其他項目恰好擁有完全相同的價格,但我認爲這將是容易提高從這裏開始