2016-03-15 37 views
1

我需要删除文档的某些字段,但我只知道我想保留的字段。除了我已知的领域,我怎样才能解除所有问题。例如:如何取消设置除某些已知字段以外的所有字段?

的文件在我的数据库看起来像下面

{ 
    "_id" : ObjectId("1234567891234"), 
    "name" : "testname", 
    "settings" : { 
    "pairing" : true} 
    "subject" : "alarm" 
} 

而且我要删除的“设置”和“主题”字段。所以它会像下面这样。

{ 
    "_id" : ObjectId("1234567891234"), 
    "name" : "testname" 
} 

但是我不能只用“$未设置”到现场,因为我只知道,我想保留的字段。

有没有办法在pymongo中做到这一点。我发现了一个相关的问题,但我不知道这是否可以在python 2.7中使用。

相关问题: How do I unset all fields except a known set of fields?

+0

是的,这是可能的。我还为这个问题添加了一个答案,以显示如何在shell中执行此操作。 – styvane

回答

0

是的,这是可能的!如果要取消设置集合中多个文档的已知字段以外的所有字段,最好的方法是使用“批量”操作。

MongoDB 3.2弃用Bulk()及其相关方法。所以如果你应该使用.bulk_write()

from itertools import zip_longest # or izip_longest in Python 2.x 
from pymongo import MongoClient, UpdateOne 


client = MongoClient() 
db = client.db 
collection = db.collection 
requests = [] 
fields = ['name', '_id'] 
for document in collection.find(): 
    unset_op = dict(zip_longest(set(document.keys()).difference(fields), [''], fill_value='')) 
    requests.append(UpdateOne({'_id': document['_id']}, {'$unset': unset_op})) 
    # Execute per 1000 operations and re-init. 
    if len(requests) == 1000: 
     collection.bulk_write(requests) 
     requests = [] 

# clean up the queues 
if requests: 
    collection.bulk_write(requests) 

对于您需要使用find_one方法,该方法返回如果您没有使用最新的符合您的条件,然后replace_one新版本3.0

document = collection.find_one({'_id': 111}) 
collection.replace_one({'_id': document['_id']}, dict(zip(fields, [document[field] for field in fields]))) 

文档一个文档版本的MongoDB或Pymongo驱动程序,您需要使用Bulk() API。

bulk = collection.initialize_unordered_bulk_op() 
count = 0 
for document in collection.find(): 
    unset_op = dict(zip_longest(set(document.keys()).difference(fields), [''], fill_value='')) 
    bulk.find({'_id': document['_id']}).update_one({'$unset': unset_op}) 
    count = count + 1 
    if count % 1000 == 0: 
     bulk.execute() 
     bulk = collection.initialize_unordered_bulk_op()   
    if count > 0: 
     bulk.execute() 

对于单个文档,您可以依赖于update_one方法。

unset_op = dict(izip_longest(set(document.keys()).difference(fields), [''], fill_value='')) 
collection.update_one({'_id': document['_id']}, {'$unset': unset_op}) 
0

一种可能的方式是没有“$集”,以更新的方式,将更新整个文档中删除例如未指定的字段:

{ 
    "_id" : ObjectId("1234567891234"), 
    "name" : "testname", 
    "settings" : { 
    "pairing" : true} 
    "subject" : "alarm" 
} 

db.collection_name.update({"_id" : ObjectId("1234567891234")},{"name" : "testname"}) 

将导致其他字段删除,但“名称”。 所以在Python中,你可以做到以下几点:

result = db.collection_name.find_one({"name":"testname"}) 

(如果你知道IDS可以搜索,但一定要导入from bson.objectid import ObjectId)。之后,您将收集结果存储在结果中。那么你想用你知道的例子更新记录:

db.collection_name.update_one({"_id":result["_id"]},{"name":result["name"]}) 

这是一种方法。它当然只会保留“名称”和“_id”,但所有其他未指定的字段将被删除。希望它有帮助

相关问题