我需要删除文档的某些字段,但我只知道要保留的字段。除了我已知的领域之外,我该怎么办?例如:
我的数据库中的文档如下所示
{
"_id" : ObjectId("1234567891234"),
"name" : "testname",
"settings" : {
"pairing" : true}
"subject" : "alarm"
}
我想删除"设置"和#34;主题"领域。所以它将如下所示。
{
"_id" : ObjectId("1234567891234"),
"name" : "testname"
}
但是我不能使用" $ unset"到一个领域,因为我只知道我想要保留的领域。
有没有办法在pymongo做到这一点。我发现了一个相关的问题,但我不知道这在python 2.7中是否完全可能。
相关问题: How do I unset all fields except a known set of fields?
答案 0 :(得分:0)
一种可能的方法是在没有“$ set”的情况下进行更新,这将更新整个文档,删除未指定的字段,例如:
{
"_id" : ObjectId("1234567891234"),
"name" : "testname",
"settings" : {
"pairing" : true}
"subject" : "alarm"
}
做
db.collection_name.update({"_id" : ObjectId("1234567891234")},{"name" : "testname"})
将导致删除其他字段,但“name”。 所以在python中你可以做到以下几点:
result = db.collection_name.find_one({"name":"testname"})
(如果你知道你可以搜索的ID,但一定要导入from bson.objectid import ObjectId
)。之后,您将集合存储在结果中。那么你想用你知道的例子记录更新:
db.collection_name.update_one({"_id":result["_id"]},{"name":result["name"]})
这是一种方法。它只会保留“名称”和“_id”,但所有其他未指定的字段将被删除。希望它有所帮助
答案 1 :(得分:0)
是的,这是可能的!如果要取消设置集合中多个文档的已知字段之外的所有字段,最好的方法是使用" bulk"操作。
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})