2016-03-15 54 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」,但所有其他未指定的字段將被刪除。希望它有幫助

相關問題