在mongo中更新字段类型

时间:2016-04-05 14:36:55

标签: python mongodb mongodb-query pymongo

我在collection中有大量记录:

{field: [value]}

如何有效地更新到:

{field:value}

我尝试过这样的事情:(pymongo syntax)

collection.update({"field.1": {"$exists": True}},
                  {"$set": {'field': "field.1"}},
                  multi=True)

显然不起作用。 由于记录数量很大,因此无法在循环中运行每个记录并删除插入。

2 个答案:

答案 0 :(得分:4)

您需要使用$set更新运算符循环游标并更新每个文档。当然,要使用" bulk"操作以实现最高效率。据说这种方法会因MongoDB服务器版本和PyMongo版本而异。

从MongoDB 3.2开始,您需要使用Bulk Write OperationsbulkWrite()方法。

var requests = [];
var cursor = db.collection.find( { "field.1": { "$exists": true } }, { "field": 1 } );
cursor.forEach( document => { 
    requests.push({ 
        "updateOne": {
            "filter" : { "_id": document._id },
            "update" : { "field": { "$set": document.field[0] } }
        }
    });
    if (requests.length === 1000) {
        db.collection.bulkWrite(requests);
        requests = [];
    }
});

if (requests.length > 0) {
    db.collection.bulkWrite(requests);
}

使用PyMongo 3.0驱动程序的此查询提供了您需要使用bulk_write()方法的内容,它提供了以下内容:

from pymongo import UpdateOne


requests = [];
cursor = db.collection.find({"field.1": {"$exists": True}}, {"field": 1})
for document in cursor:
    requests.append(UpdateOne({'_id': document['_id']}, {'$set': {'field': document['field'][0]}}))
    if len(requests) == 1000:
        # Execute per 1000 operations
        db.collection.bulk_write(requests)
        requests = []
if len(requests) > 0:

    # clean up queues
    db.collection.bulk_write(requests)

从MongoDB 2.6开始,您需要使用现已弃用的Bulk API。

var bulk = db.collection.initializeUnorderedBulkOp();
var count = 0;

// cursor is the same as in the previous version using MongoDB 3.2
cursor.forEach(function(document) { 
    bulk.find( { "_id": document._id } ).updateOne( { "$set": { "field": document.field[0] } } ); 
    count++;
    if (count % 1000 === 0) {
        bulk.execute();
        bulk = db.collection.initializedUnorderedBulkOp();
    }
});

// Again clean up queues
if (count > 0 ) {
    bulk.execute();
}

转换为Python提供以下内容。

bulk = db.collection.initialize_unordered_bulk_op()
count = 0

for doc in cursor:
    bulk.find({'_id': doc['_id']}).update_one({'$set': {'field': doc['field'][0]}})
    count = count + 1
    if count == 1000:
        bulk.execute()
        bulk = db.collection.initialize_unordered_bulk_op()

if count > 0:
    bulk.execute()

答案 1 :(得分:1)

如果您的数组只有一个元素,那么您的更新将无法正常工作,因为在JavaScript中(mongodb受到很大影响)the first array index is 0。这应该有效:

collection.update({"field.0": {"$exists": True}},
                  {"$set": {'field': "field.0"}},
                  multi=True)