mongodb: update

本文详细介绍了MongoDB中update操作的使用方法,包括查询文档、修改器、upsert选项及批量更新策略。通过实例展示了如何使用shell命令进行文档的添加、修改、删除等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如此明媚春光,正是打望好时节,恰周末楼下周边溜达,热,遂归。来折腾我的mongodb学习计划。现在应该是看到update部分了,参考《MongoDB权威指南》

update
update({},{},boolean,boolean)
shell命令update接受四个参数
1、查询文档:找出需要更新的文档
2、修改器:描述对文档的修改
3、upsert:没有文档符合更新条件,则创建改记录。默认false不支持
4、更新默认只会对满足条件的第一条记录更新,支持批量设置true

 

1、采用shell命令更新 ,首先获取查询结果,对结果进行修改再操作

获取一个document对象

> var user = db.users.findOne()
> user
{
	"_id" : ObjectId("4f62ef1cb678c1a3326549e6"),
	"name" : "robin",
	"age" : 30,
	"friends" : 32
}

 新增address属性,并更新操作

> user.address = {"city":"chengdu","street":"asdasdfas"}
{ "city" : "chengdu", "street" : "asdasdfas" }
> db.users.update({"name":"robin"},user)
> db.users.findOne()
{
	"_id" : ObjectId("4f62ef1cb678c1a3326549e6"),
	"name" : "robin",
	"age" : 30,
	"friends" : 32,
	"address" : {
		"city" : "chengdu",
		"street" : "asdasdfas"
	}
}

 其他的一些操作

> delete user.age
true
> user
{
	"_id" : ObjectId("4f62ef1cb678c1a3326549e6"),
	"name" : "robin",
	"friends" : 32,
	"address" : {
		"city" : "chengdu",
		"street" : "asdasdfas"
	}
}

 书中提到了对批量数据的修改,在查询时返回了多条记录,不能直接调用update,是由于在update时会匹配多条记录,而实际更新的会与记录中的其他"_id"不一致。但是在我测试的版本2.0.2中,貌似没有这样的错误发生,难道已经改变了update策略:

#根据name查找有四条记录
> db.users.find({"name":"robin"})
{ "_id" : ObjectId("4f62ef1cb678c1a3326549e6"), "name" : "robin", "age" : 31, "friends" : 32, "address" : { "city" : "chengdu", "street" : "asdasdfas" } }
{ "_id" : ObjectId("4f62f5b8b678c1a3326549e7"), "name" : "robin", "age" : 20, "foo" : "bar" }
{ "_id" : ObjectId("4f62f5c6b678c1a3326549e8"), "name" : "robin", "age" : 30, "foo" : "bar" }
{ "_id" : ObjectId("4f62f5cdb678c1a3326549e9"), "name" : "robin", "age" : 40, "foo" : "bar" }
#只选取一条,并对其属性进行设置
> robin = db.users.findOne({"name":"robin"})
{
	"_id" : ObjectId("4f62ef1cb678c1a3326549e6"),
	"name" : "robin",
	"age" : 31,
	"friends" : 32,
	"address" : {
		"city" : "chengdu",
		"street" : "asdasdfas"
	}
}
> robin.age++
31
> db.users.update({"name":"robin"}, robin)
#查看结果只有第一条已经改变,但整个过程中并没有报错
> db.users.find()
{ "_id" : ObjectId("4f62ef1cb678c1a3326549e6"), "name" : "robin", "age" : 32, "friends" : 32, "address" : { "city" : "chengdu", "street" : "asdasdfas" } }
{ "_id" : ObjectId("4f62f5b8b678c1a3326549e7"), "name" : "robin", "age" : 20, "foo" : "bar" }
{ "_id" : ObjectId("4f62f5c6b678c1a3326549e8"), "name" : "robin", "age" : 30, "foo" : "bar" }
{ "_id" : ObjectId("4f62f5cdb678c1a3326549e9"), "name" : "robin", "age" : 40, "foo" : "bar" }
 

2、使用修改器修改

就是指前面update中的第二个参数,这里包括一系列的命令。下面就各个命名来分别说明

  • $set

$set用来指定一个键的值,如果不存在就创建

> db.users.findOne()
{ "_id" : 1, "name" : "robin", "age" : 30, "gender" : "male" }
#修改age的值和新增属性foo
>  db.users.update({"name":"robin"},{"$set":{"age":40, "foo":"bar"}})
> db.users.findOne()
{
	"_id" : 1,
	"age" : 40,
	"foo" : "bar",
	"gender" : "male",
	"name" : "robin"
}
#修改属性的类型
> db.users.update({"name":"robin"},{"$set":{"age":"zzzz", "foo":["aaaa","bbbbb"]}})
> db.users.findOne()
{
	"_id" : 1,
	"age" : "zzzz",
	"foo" : [
		"aaaa",
		"bbbbb"
	],
	"gender" : "male",
	"name" : "robin"
}
#修改内嵌文档
> db.users.update({"name":"robin"},{"$set":{"address":{"city":"chengdu", "street":"aaaaaaaaaa"}}})
> db.users.findOne()
{
	"_id" : 1,
	"address" : {
		"city" : "chengdu",
		"street" : "aaaaaaaaaa"
	},
	"age" : "zzzz",
	"foo" : [
		"aaaa",
		"bbbbb"
	],
	"gender" : "male",
	"name" : "robin"
}
> db.users.update({"name":"robin"},{"$set":{"address.street":"bbbbbbbbbbbbbbbb"}})
> db.users.findOne()
{
	"_id" : 1,
	"address" : {
		"city" : "chengdu",
		"street" : "bbbbbbbbbbbbbbbb"
	},
	"age" : "zzzz",
	"foo" : [
		"aaaa",
		"bbbbb"
	],
	"gender" : "male",
	"name" : "robin"
}
 
  • $unset

用来移除一个文档的属性

> db.users.findOne()
{
	"_id" : 1,
	"address" : {
		"city" : "chengdu",
		"street" : "bbbbbbbbbbbbbbbb"
	},
	"age" : "zzzz",
	"foo" : [
		"aaaa",
		"bbbbb"
	],
	"gender" : "male",
	"name" : "robin"
}
> db.users.update({"name":"robin"},{"$unset":{"foo":1,"address":-1}})
> db.users.findOne()
{ "_id" : 1, "age" : "zzzz", "gender" : "male", "name" : "robin" }

 这里属性后面的数字该是什么呢,貌似没什么限制

#正数负数都试过了
> db.users.update({"name":"robin"},{"$unset":{"age":0,"address":-1}})
> db.users.findOne()
{ "_id" : 1, "gender" : "male", "name" : "robin" }
#把查找条件也给unset了
> db.users.update({"name":"robin"},{"$unset":{"name":0,"address":-1}})
> db.users.findOne()
{ "_id" : 1, "gender" : "male" }
 
  • $inc

增加或减少,这个只针对文档类型为整数、长整数或双精度浮点数。如果修改的键不存在则创建,其值为指定的数值。否则在该键上做相应的增加或减少

> db.users.find()
{ "_id" : ObjectId("4f630319b678c1a3326549ea"), "address" : { "city" : "chengdu", "street" : "bbbbbbbbbbbbbbbb" }, "age" : "zzzz", "gender" : "male", "name" : "robin" }
#当age不是数值类型时会报错
> db.users.update({"name":"robin"},{"$inc":{"age":10}})
Cannot apply $inc modifier to non-number
#修改为数值类型
> db.users.update({"name":"robin"},{"$set":{"age":10}})
> db.users.find({"name":"robin"})
{ "_id" : ObjectId("4f630319b678c1a3326549ea"), "address" : { "city" : "chengdu", "street" : "bbbbbbbbbbbbbbbb" }, "age" : 10, "gender" : "male", "name" : "robin" }
#同时更新,age键存在增加10,foo键不存在,创建foo并设置为30。如果要减少,只需要为负数即可
> db.users.update({"name":"robin"},{"$inc":{"age":10, "foo":30}})
> db.users.find({"name":"robin"})
{ "_id" : ObjectId("4f630319b678c1a3326549ea"), "address" : { "city" : "chengdu", "street" : "bbbbbbbbbbbbbbbb" }, "age" : 20, "foo" : 30, "gender" : "male", "name" : "robin" }
 
  • $push

数组修改器,会向已有的数组末尾加入一元素,没有则创建新的数组(注意是数组,最开始看到时我还在想用set也可以实现,当然其set的值本身就是一个数组例外)

> db.blog.insert({"title":"mongodb learn","owner":"duuuu","content":"content....."})
> db.blog.findOne()
{
	"_id" : ObjectId("4f636a2b3c82ae09f9857f29"),
	"title" : "mongodb learn",
	"owner" : "duuuu",
	"content" : "content....."
}

#插入一条评论,将会创建comments键,并为数组结构
> db.blog.update({"owner":"duuuu"},{"$push":{"comments":{"name":"joe", "email":"mongodb@sample","content":"good"}}})
> db.blog.findOne()
{
	"_id" : ObjectId("4f636a2b3c82ae09f9857f29"),
	"comments" : [
		{
			"name" : "joe",
			"email" : "mongodb@sample",
			"content" : "good"
		}
	],
	"content" : "content.....",
	"owner" : "duuuu",
	"title" : "mongodb learn"
}

#继续插入
> db.blog.update({"owner":"duuuu"},{"$push":{"comments":{"name":"ace", "email":"ace@sample","content":"nice"}}})
> db.blog.find()
{ "_id" : ObjectId("4f636a2b3c82ae09f9857f29"), "comments" : [ 	{ 	"name" : "joe", 	"email" : "mongodb@sample", 	"content" : "good" }, 	{ 	"name" : "ace", 	"email" : "ace@sample", 	"content" : "nice" } ], "content" : "content.....", "owner" : "duuuu", "title" : "mongodb learn" }

#批量新增
> db.users.insert({"name":"robin", "address":"chengdu", "age":30})
> db.users.update({"name":"robin"},{"$push":{"emails":{"$each":["sam@sample.com","dddd@sample.com","joe@sample.com"]}}})
> db.users.find()
{ "_id" : ObjectId("4f6421def1c05dbbfa7b6ff7"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }

 

  • $addToSet

类似saveandupdate没有就更新,有了就不再重复添加。需要注意的是只能对数组类型操作

> db.users.insert({"name":"robin", "address":"chengdu", "age":30})
> db.users.find()
{ "_id" : ObjectId("4f64179ef1c05dbbfa7b6ff5"), "name" : "robin", "address" : "chengdu", "age" : 30 }
> db.users.update({"name":"robin"},{"$addToSet":{"age":33}})
Cannot apply $addToSet modifier to non-array

#现在修改为数组
> db.users.find()
{ "_id" : ObjectId("4f641b65f1c05dbbfa7b6ff6"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com" ], "name" : "robin" }
> db.users.update({"name":"robin"},{"$push":{"emails":"abc@sample.com"}})
> db.users.find()
{ "_id" : ObjectId("4f641b65f1c05dbbfa7b6ff6"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "abc@sample.com" ], "name" : "robin" }
#新增一个数组中不存在的属性
> db.users.update({"name":"robin"},{"$addToSet":{"emails":"abcd@sample.com"}})
> db.users.find()
{ "_id" : ObjectId("4f641b65f1c05dbbfa7b6ff6"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "abc@sample.com", "abcd@sample.com" ], "name" : "robin" }
#新增一个存在的属性
> db.users.update({"name":"robin"},{"$addToSet":{"emails":"abcd@sample.com"}})
> db.users.find()
{ "_id" : ObjectId("4f641b65f1c05dbbfa7b6ff6"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "abc@sample.com", "abcd@sample.com" ], "name" : "robin" }
#批量新增
> db.users.update({"name":"robin"},{"$addToSet":{"emails":{"$each":["sam@sample.com","dddd@sample.com","joe@sample.com"]}}})
> db.users.find()
{ "_id" : ObjectId("4f641b65f1c05dbbfa7b6ff6"), "address" : "chengdu", "age" : 30, "emails" : [ 	"sam@sample.com", 	"abc@sample.com", 	"abcd@sample.com", 	"dddd@sample.com", 	"joe@sample.com" ], "name" : "robin" }

 

  • 从数组删除元素

$pop
{"$pop":{key:1}} 从数组末尾删除
{"$pop":{key:-1}} 从数组头部删除

> db.users.find()
{ "_id" : ObjectId("4f6421def1c05dbbfa7b6ff7"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }
#从数组末尾删
> db.users.update({"name":"robin"},{"$pop":{"emails":1}})
> db.users.find()
{ "_id" : ObjectId("4f6421def1c05dbbfa7b6ff7"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "dddd@sample.com" ], "name" : "robin" }
#从数组头部删
> db.users.update({"name":"robin"},{"$pop":{"emails":-1}})
> db.users.find()
{ "_id" : ObjectId("4f6421def1c05dbbfa7b6ff7"), "address" : "chengdu", "age" : 30, "emails" : [ "dddd@sample.com" ], "name" : "robin" }

 

$pull

用于删除指定的元素,如果元素不存在不报错

> db.users.find()
{ "_id" : ObjectId("4f64244ff1c05dbbfa7b6ff8"), "address" : "chengdu", "age" : 30, "emails" : [ "sam@sample.com", "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }
> db.users.update({"name":"robin"},{"$pull":{"emails":"sam@sample.com"}})
> db.users.find()
{ "_id" : ObjectId("4f64244ff1c05dbbfa7b6ff8"), "address" : "chengdu", "age" : 30, "emails" : [ "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }
> db.users.update({"name":"robin"},{"$pull":{"emails":"sam@sample.com"}})
> db.users.find()
{ "_id" : ObjectId("4f64244ff1c05dbbfa7b6ff8"), "address" : "chengdu", "age" : 30, "emails" : [ "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }
#尝试了批量删除,但是这样貌似不管用
> db.users.update({"name":"robin"},{"$pull":{"emails":{"$each":["sam@sample.com","joe@sample.com"]}}})
> db.users.find()
{ "_id" : ObjectId("4f64244ff1c05dbbfa7b6ff8"), "address" : "chengdu", "age" : 30, "emails" : [ "dddd@sample.com", "joe@sample.com" ], "name" : "robin" }
 
  • 数组定位修改

这里对数组中其中一部分数据进行操作,可通过下标或者定位符$操作

> db.blog.find()
{ "_id" : ObjectId("4f636a2b3c82ae09f9857f29"), "comments" : [ 	{ 	"name" : "joe", 	"email" : "mongodb@sample", 	"content" : "good" }, 	{ 	"name" : "ace", 	"email" : "ace@sample", 	"content" : "nice" }, 	{ 	"name" : "sam", 	"email" : "sam@sample", 	"content" : "ding" } ], "content" : "content.....", "owner" : "duuuu", "title" : "mongodb learn" }
#对数组comments第一条记录增加foo属性。这里下标是从0开始
> db.blog.update({"owner":"duuuu"},{"$set":{"comments.0.foo":"bar"}})
> db.blog.find()
{ "_id" : ObjectId("4f636a2b3c82ae09f9857f29"), "comments" : [ 	{ 	"content" : "good", 	"email" : "mongodb@sample", 	"foo" : "bar", 	"name" : "joe" }, 	{ 	"name" : "ace", 	"email" : "ace@sample", 	"content" : "nice" }, 	{ 	"name" : "sam", 	"email" : "sam@sample", 	"content" : "ding" } ], "content" : "content.....", "owner" : "duuuu", "title" : "mongodb learn" }

#设置comments中两条name记录一致
> db.blog.update({"owner":"duuuu"},{"$set":{"comments.1.name":"joe"}})
#定位操作符($),只会对匹配的第一条记录做修改
> db.blog.update({"comments.name":"joe"},{"$set":{"comments.$.name":"jim"}})
> db.blog.find()
{ "_id" : ObjectId("4f636a2b3c82ae09f9857f29"), "comments" : [ 	{ 	"content" : "good", 	"email" : "mongodb@sample", 	"foo" : "bar", 	"name" : "jim" }, 	{ 	"name" : "joe", 	"email" : "ace@sample", 	"content" : "nice" }, 	{ 	"name" : "sam", 	"email" : "sam@sample", 	"content" : "ding" } ], "content" : "content.....", "owner" : "duuuu", "title" : "mongodb learn" }

#采用批量的方式,貌似还是不管用
> db.blog.update({"owner":"duuuu"},{"$set":{"comments.0.name":"joe"}})
> db.blog.update({"comments.name":"joe"},{"$set":{"comments.$.name":"jim"}},false,true)
> db.blog.find()
{ "_id" : ObjectId("4f636a2b3c82ae09f9857f29"), "comments" : [ 	{ 	"content" : "good", 	"email" : "mongodb@sample", 	"foo" : "bar", 	"name" : "jim" }, 	{ 	"name" : "joe", 	"email" : "ace@sample", 	"content" : "nice" }, 	{ 	"name" : "sam", 	"email" : "sam@sample", 	"content" : "ding" } ], "content" : "content.....", "owner" : "duuuu", "title" : "mongodb learn" }

 

  • upsert

如果没有符合条件的记录,就会以这个条件和更新的document创建一个新的记录,如果有则正常更新。通过将update的第三个参数设为true来调用

> db.users.update({"name":"robinn"},{"$set":{"foo":"bar"}},true)
> db.users.find()
{ "_id" : 1, "age" : 30, "foo" : "bar", "name" : "robin" }
{ "_id" : 2, "age" : 31, "foo" : "bar", "name" : "robin" }
{ "_id" : 3, "age" : 32, "foo" : "bar", "name" : "robin" }
{ "_id" : ObjectId("4f6459f52ba49049835032c5"), "foo" : "bar", "name" : "robinn" }
 
  • 更新多个document

在update中,如果有多个匹配的更新结果,默认只会更新第一个,在update中的第四个参数设置true就会对匹配的结果同时更新

> db.users.find({"name":"robin"})
{ "_id" : 1, "name" : "robin", "age" : 30 }
{ "_id" : 2, "name" : "robin", "age" : 31 }
{ "_id" : 3, "name" : "robin", "age" : 32 }
#只会对匹配条件的第一条记录更新
> db.users.update({"name":"robin"},{"$set":{"foo":"bar"}})
> db.users.find({"name":"robin"})
{ "_id" : 1, "age" : 30, "foo" : "bar", "name" : "robin" }
{ "_id" : 2, "name" : "robin", "age" : 31 }
{ "_id" : 3, "name" : "robin", "age" : 32 }
#将第四个参数设置true,此时将会更新所有查找到的记录
> db.users.update({"name":"robin"},{"$set":{"foo":"bar"}},false,true)
> db.users.find({"name":"robin"})
{ "_id" : 1, "age" : 30, "foo" : "bar", "name" : "robin" }
{ "_id" : 2, "age" : 31, "foo" : "bar", "name" : "robin" }
{ "_id" : 3, "age" : 32, "foo" : "bar", "name" : "robin" }

 

关于修改器的速度,保持一个原则:如果修改操作不需要修改document的大小,那么非常快,否则性能会有所下降
如$inc只是对document的值修改那么将是快速的,而$set如果是对document新增了属性那么性能会有所下降,如果只是改变某个值也会很快。而数组修改器一般改变了document的大小,故性能会有下降

 

### 解决PyCharm无法加载Conda虚拟环境的方法 #### 配置设置 为了使 PyCharm 能够成功识别并使用 Conda 创建的虚拟环境,需确保 Anaconda 的路径已正确添加至系统的环境变量中[^1]。这一步骤至关重要,因为只有当 Python 解释器及其关联工具被加入 PATH 后,IDE 才能顺利找到它们。 对于 Windows 用户而言,在安装 Anaconda 时,默认情况下会询问是否将它添加到系统路径里;如果当时选择了否,则现在应该手动完成此操作。具体做法是在“高级系统设置”的“环境变量”选项内编辑 `Path` 变量,追加 Anaconda 安装目录下的 Scripts 文件夹位置。 另外,建议每次新建项目前都通过命令行先激活目标 conda env: ```bash conda activate myenvname ``` 接着再启动 IDE 进入工作区,这样有助于减少兼容性方面的问题发生概率。 #### 常见错误及修复方法 ##### 错误一:未发现任何解释器 症状表现为打开 PyCharm 新建工程向导页面找不到由 Conda 构建出来的 interpreter 列表项。此时应前往 Preferences/Settings -> Project:...->Python Interpreter 下方点击齿轮图标选择 Add...按钮来指定自定义的位置。按照提示浏览定位到对应版本 python.exe 的绝对地址即可解决问题。 ##### 错误二:权限不足导致 DLL 加载失败 有时即使指定了正确的解释器路径,仍可能遇到由于缺乏适当的操作系统级许可而引发的功能缺失现象。特别是涉及到调用某些特定类型的动态链接库 (Dynamic Link Library, .dll) 时尤为明显。因此拥有管理员身份执行相关动作显得尤为重要——无论是从终端还是图形界面触发创建新 venv 流程均如此处理能够有效规避此类隐患。 ##### 错误三:网络连接异常引起依赖下载超时 部分开发者反馈过因网速慢或者其他因素造成 pip install 操作中途断开进而影响整个项目的初始化进度条卡住的情况。对此可尝试调整镜像源加速获取速度或是离线模式预先准备好所需资源包后再继续后续步骤。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值