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

我有一个 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 价格项目?

4

3 回答 3

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 记录。如果您想删除所有“非最高”价格,那么您需要找到最高价格和该价格$pull的所有元素$lt

于 2013-09-29T07:15:19.350 回答
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}}}
        )

当然,如果另一个项目恰好具有完全相同的价格,这里就会出现问题,但我认为从这里改进会很容易

于 2017-04-07T13:26:41.127 回答
0
{'$pull': {'items': {item['type']}}}

This doesn't look like valid json, does it?

shouldn't be "sales.update(...)" be "db.sales.update(...)" in your example?

maybe it's better to have query in update operation:

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

rather than entire doc.

and finally the update body itself might be

{'$pull': {'items': {type: item['type']}}}
于 2013-09-28T12:43:50.980 回答