MongoDB:文档增删改查

Document文档

在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据。

MongoDB中的文档地数据结构和JSON基本一样,所有存储在集合中地数据都是BSON。

新增文档

insert

此方法是插入文档最常用的方法,可以插入单条或多条文档。

语法格式:

db.collection.insert(
<document or documents>,
{
	writeConcern:<document>,
	ordered:<boolean>
}
)

参数说明:

document or documents:一条文档或多条文档

  • 一条:{doc}
  • 多条:[{doc1},{doc2}...]

writeConcern:可选参数,表示是否使用写入策略,该策略较为复杂,这里暂不讨论

ordered:是否为有序插入,默认为true

  • true:文档中有一个发生错误,mongodb将不再继续插入后续文档
  • false:当文档有一个发生错误,不会影响后续文档地插入
db.user.insert(
[{ 'name':'wj','age':23},{'name':'zhangsan','age':20}]
)

image-20210110165048522

save

save也可以插入一条或多条文档,但是insert方法插入主键相同的文档时会报错,而使用save方法插入主键相同的文档时则会覆盖原文档。

db.collection.save(
<document or documents >,
{
	writeConcern:<document>
}
)

insertOne

insertOne只能插入一条文档,如果使用该方法插入多条文档,则mongodb只会新增第一条文档。

db.collection.insertOne(
<document>,
{
	writeConcern:<document>
}
)

insertMany

该方法可以插入多个文档,语法与insert方法一样,插入成功后,会返回插入文档的主键。

image-20210110165645134

注意,使用insertMany插入单条文档,也必须用中括号括起来,否则报错。

image-20210110170041454

变量定义和使用

test_user=({ 'name':'wj','age':23})
db.user.insert(test_user)
test_user2=([{ 'name':'wj','age':23},{ 'name':'wj2','age':24}])
db.user.insertMany(test_user2)

image-20210110170615689

查询文档

find

语法格式:

db.collection.find(<query>,<projection>);

参数说明:

  • 如果不指定参数(参数为空,则查询该集合中所有文档)
  • query:查询条件
  • projection:该参数可以指定查询结果中需要显示的字段,设置为1,表示显示,为0,则不显示。"_id"字段默认显示。当设置"_id"为1时,其他字段必须为1,否则报错。

image-20210110172614076

查询name等于zhangsan,age等于20的文档:

db.user.find({'name':'zhangsan','age':20})

image-20210110172829459

比较操作符

  • 小于 $lt
  • 小于等于 $lte
  • 大于 $gt
  • 大于等于 $gte
  • 不等于$ne
  • 等于 $eq
  • 包含 $in
  • 不包含 $nin

查询age小于22的文档

db.user.find({'age':{'$lt':22}})

查询age大于等于22的文档

db.user.find({'age':{'$gte':22}})

查询age不等于23的文档:

db.user.find({'age':{'$ne':23}})

image-20210110173337445

查询name值为wj或为zhangsan的文档:

db.user.find({'name':{'$in':['wj','zhangsan']}})

字母比较:

按照字母顺序比较:查询name第一个字符比x小的文档

db.user.find({'name':{'$lt':'x'}})

image-20210110173530215

逻辑操作符

总共4种,不过多介绍:$and,$nor,$or,$not

查询name不是wj的文档:

db.user.find({'name':{'$not':{'$eq':'wj'}}})

findOne

查询符合条件的第一个文档(自然排序),参数与find方法一样

db.user.findOne({'name':{'$lt':'x'}})

image-20210110173832597

pretty格式化

使用pretty()方法可以格式化查询返回结果,知道有这一个方法就好,我的查询器默认已经格式化了。

findOne()默认会格式化返回结果,所以无需加上pretty()。

db.collection.find().pretty();

复杂查询条件

并列条件:查询age大于等于22,小于等于24的文档

db.user.find({'age':{'$gte':22, '$lte':24}})

或者条件:查询age大于等于22、小于等于24,或者name等于zhangsan的文档

对于这种,语法格式如下:

# db.collection.find({'$or':[{},{}...]})

db.user.find({'$or':
    [
        {'name':'zhangsan'}
        ,{'age':{'$gte':22, '$lte':24}}
    ]
})

$type查询

根据集合中某个属性的类型查询对应的数据,使用$type指定属性类型

例如:查询name属性为字符串的文档

db.user.find({'name':{'$type':'string'}})

在mongodb中,数字类型默认都是double

db.user.find({'age':{'$type':'double'}})

image-20210110175917040

$type有效值如下

type number Alias
Double 1 double
String 2 string
Object 3 object
Array 4 array
Binary data 5 binData
Undefined 6 undefined
ObjectId 7 objectId
Boolean 8 bool
Date 9 date
Null 10 null
Regular Expression 11 regex
DBPointer 12 dbPoint
JavaScript 13 javascript
Symbol 14 symbol
JavaScript(with scope) 15 javascriptWithScope
32-bit integer 16 int
Timestamp 17 timestamp
64-bit integer 18 long
Decimal128 19 decimal

正则查询

简写

语法:

db.collection.find({field:/pattern/})

查询name中以z开头的文档

db.user.find({'name':/^z/})

查询name中以n结尾的文档:

db.user.find({'name':/n$/})

查询name中以z开头、以n结尾的文档(.* 意为多个任意字符)

db.user.find({'name':/^z.*n$/})

查询name中包含w字符的文档

db.user.find({'name':/w/})

查询name中包含w字符(忽略大小写)

db.user.find({'name':/w/i})

差不多了解以上的正则在实际开发中就够用了,那些需要邮箱正则、手机号正则的场景,为什么不在插入数据之前就做处理呢?

全写

语法:

db.collection.find({field:{$regex:/pattern/,$options:'<options>'}})
db.collection.find({field:{$regex:/pattern/<options>}})

部分操作符也支持正则表达式

例如:查询name以z开头,或以n结尾的文档

db.user.find({'name':{'$in':[/^z/,/n$/]}})

image-20210110183333014

查询name不以z开头的文档

db.user.find({'name':{'$not':/^z/}})

分页查询

结合limit()和skip()方法完成分页

limit:限制多少条返回

skip:跳过前多少条,并返回

查询第一页数据,一页三条(查询三条,跳过零条)

db.user.find().limit(3).skip(0);
db.user.find().limit(3);

查询第二页数据,一页三条(查询三条,跳过三条)

db.user.find().limit(3).skip(3);

不跳过任何数据,只查询前三条

db.user.find().limit(3);

跳过前三条数据,查询剩余所有数据

db.user.find().skip(3);

有点像mysql的limit n,m 跳过n行查询m行

排序查询

使用sort()方法即可排序

# age列的升序
db.user.find().sort({'age':1});
# age列的降序
db.user.find().sort({'age':-1});
# 先age升序,再name降序
db.user.find().sort({'age':1,'name':-1});

更新文档

mongodb主要通过save(覆盖)和update(修改)来更新文档。

save

save的作用是保存文档,如果文档存在则覆盖,不存在则插入。save对文档的存在判断标准是"_id"是否存在。所以如果想用save去更新文档,则必须带上该字段,且该字段在集合中已经存在。

db.user.save({"_id" : ObjectId("5ffac1b0a1761355478cf855"),'name':'lisi','age':19});

image-20210110185945394

使用save,如果文档不存在并新增成功,则nUpserted为1,如果存在并修改成功,则nModified为1

update

该方法可以通过特定条件来更新一个或多个文档。

语法格式(其实后面可以携带更多参数,这里仅简单介绍基本用法):

db.collection.update(<query>,<update>);

参数说明:

  • query 更新文档的筛选条件
  • update 更新的字段和字段值

覆盖修改

把name等于wj的文档,变为age等于23(注意,update默认情况下只覆盖匹配到的第一条文档)

db.user.update({'name':'wj'},{'age':23})

image-20210110191440806

上图为覆盖后的结果,name字段丢失了,是因为没有写name字段,直接用{'age':23}覆盖了原来的文档

表达式更新

$set

把name等于wj的文档的age修改为25(这里也修改匹配到的第一条文档)

db.user.update({'name':'wj'},{'$set':{'age':25}})

这里$set的字段,如果字段存在,则修改字段,如果不存在,则添加字段

$inc

将字段增加指定的值

把name等于wj的文档的age增加10

db.user.update({'name':'wj'},{'$inc':{'age':10}})
$unset

把对应的字段删除

把name等于wj的文档的age删除

#age字段的值任意写,这里只是一个占位标记
db.user.update({'name':'wj'},{'$unset':{'age':1}})
$push

这里先给name等于wj的文档添加一个字段courses课程,该字段是一个数组

db.user.update({'name':'wj'},{'$set':{'courses':['springboot','springcloud']}})

image-20210110192908650

现在我想向courses字段中添加一个元素docker

db.user.update({'name':'wj'},{'$push':{'courses':'docker'}})

image-20210110193150577

注意:以下的写法不是添加多个元素,而是往courses字段中添加了一个数组,所以push只能往数组中添加一个元素(无论是该元素数组还是其他)

db.user.update({'name':'wj'},{'$push':{'courses':['jenkins','harbor']}})

image-20210110193311978

如果push的字段不存在,则会新增一个字段,将元素放在数组中

db.user.update({'name':'wj'},{'$push':{'course':['springboot','springcloud']}})

image-20210110193719342

$addToSet

与push类似,该表达式也会向数组中添加元素,如果该元素存在,则不添加否则添加进入数组。

元素的匹配大小写敏感。

db.user.update({'name':'wj'},{'$addToSet':{'courses':'springboot2'}})
$pop

出栈(删除出来的数据),与push(压栈)相反

#删除courses数组的最后一个元素
db.user.update({'name':'wj'},{'$pop':{'courses':1}})
#删除courses数组的第一个元素
db.user.update({'name':'wj'},{'$pop':{'courses':-1}})
$pull

推(删除指定元素)

#删除courses数组中所有名称为docker的元素
db.user.update({'name':'wj'},{'$pull':{'courses':'docker'}})
$pullAll

推(删除多个指定元素)

db.user.update({'name':'wj'},{'$pullAll':{'courses':['docker','springcloud']}})

执行前:

image-20210110195451844

执行后:

image-20210110195525385

$rename

修改字段名

# 将name=wj的文档中,字段名从name修改为user_name
db.user.update({'name':'wj'},{'$rename':{'name':'user_name'}})

upset和multi

db.collection.update(<query>,<update>,<upset:boolean>,<multi:boolean>);

对于update方法,还有两个参数可以选择,upset和multi

  • upset:默认为false,为true时,则表示在更新条件没有匹配时,会插入此文档,为false则不插入。
  • multi:默认为false,为true时,会更新所有匹配到的文档,为false,则会更新匹配到的第1个文档。
#将所有name=wj的文档的age修改为25
db.user.update({'name':'wj'},{'$set':{'age':25}},false,true)
#  db.user.update({'name':'wj'},{'age':23},false,true) 该写法错误,多行操作不支持覆盖修改

删除文档

remove(不推荐)

删除所有age大于等于28的文档

db.user.remove({'age':{'$gte':28}});

删除第一条age大于等于20的文档

db.user.remove({'age':{'$gte':20}},true);

deleteOne

该方法只能删除匹配到的第一个文档

删除第一个age大于等于28的文档

db.user.deleteOne({'age':{'$gte':28}});

deleteMany

一次性删除所有匹配到的文档

删除所有age大于等于28的文档

db.user.deleteMany({'age':{'$gte':28}});
原文地址:https://www.cnblogs.com/wwjj4811/p/14259401.html