三.MongoDB入门-Mongodb的CRUD
Posted 墨家巨子@俏如来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三.MongoDB入门-Mongodb的CRUD相关的知识,希望对你有一定的参考价值。
1.MongDB核心概念
mongodb是最像关系型数据库的非关系数据库,其中很多思想和关系数据库很像,在mongodb中有几个核心概念:文档、集合、数据库如下:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
下面是数据库 , 集合 , 文档的包含关系图:
下面是关系型数据库表记录和mongdodb的文档对应关系图
1.1.数据库database
一个mongodb中可以建立多个数据库,默认数据库为"db",数据库存储在data目录中,不同的数据库也放置在不同的文件中,数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串。
- 不能是空字符串("")。
- 不得含有’ '(空格)、.、$、/、\\和\\0 (空字符)。
- 应全部小写。
- 最多64字节。
MongoDB默认保留了几个数据库:
- admin : admin数据库则主要存储MongoDB的用户、角色等信息。
- local : local数据库主要存储副本集的元数据,它只会在本地存储数据
- config : 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
1.2.集合collections
一个集合包含一堆 MongoDB 文档,如果把mysql中的一行行数据当做一个个文档,一张张表格就相当于是MongoDB中的集合
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。 合法的集合名:
- 集合名不能是空字符串""。
- 集合名不能含有\\0字符(空字符),这个字符表示集合名的结尾。
- 集合名不能以"system."开头,这是为系统集合保留的前缀。
- 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
1.3.文档document
通常一个对象可以映射成一个文档
,文档是一组键值(key-value)对(即 BSON,类似于JSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
需要注意的是:
- 文档中的键/值对是有序的。
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
- MongoDB区分类型和大小写。
- MongoDB的文档不能有重复的键。
- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
- 键不能含有\\0 (空字符)。这个字符用来表示键的结尾。
- .和$有特别的意义,只有在特定环境下才能使用。
- 以下划线"_"开头的键是保留的(不是严格要求的)。
1.4.MongoDB 数据类型
下表为MongoDB中常用的几种数据类型。
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 javascript 代码。 |
Regular expression | 正则表达式类型。用于存储正则表达式。 |
2.数据库操作
一个mongodb中可以建立多个数据库。MongoDB的默认数据库为"db",该数据库存储在data目录中。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
2.1.创建数据库
语法 use DATABASE_NAME
,如果数据库不存在,则创建数据库,否则切换到指定数据库。
实例:使用cmd ,输入mongo 进入mongo客户端终端,以下实例我们创建了数据库 hrm
> C:\\Users\\whale>mongo
> use hrm
switched to db hrm
2.2.显示所有数据库
如果你想查看所有数据库,可以使用 show dbs
命令:
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
可以看到,我们刚创建的数据库 hrm 并不在数据库的列表中, 要显示它,我们需要向 hrm 数据库插入一些数据。
使用 : db.数据库名.insert(BSON)
插入数据:
> db.hrm.insert("name":"mongdb")
WriteResult( "nInserted" : 1 )
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
hrm 0.000GB
MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。
2.3.删除数据库
需要使用use 数据库
切换到数据库之后,执行db.dropDatabase()
> use hrm //切换到hrm数据库
switched to db hrm
> db.dropDatabase() //删除数据库
"dropped" : "hrm", "ok" : 1
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
>
3.集合(表)的操作
3.1.显示集合
如果要查看已有集合,可以使用 show collections
或 show tables
命令:
> use 数据库
> show tables
3.2.创建新集合
MongoDB 中使用 db.createCollection(name,options)
方法来创建集合。
db.createCollection("mycol", capped : true, autoIndexId : true, size : 6142800, max : 10000 )
参数说明:
- name: 要创建的集合名称
- options: 可选参数, 指定有关内存大小及索引的选项
options 可以是如下参数:
字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
autoIndexId | 布尔 | 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。 |
size | 数值 | (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。
实例:在 test 数据库中创建 hrm 集合:
> use hrm
switched to db hrm
> db.createCollection("user")
"ok" : 1
创建固定集合 mycol,整个集合空间大小 6142800 B, 文档最大个数为 10000 个。
> db.createCollection("mycol",capped:true,autoIndexId:true,size:6142800,max:10000)
"ok" : 0,
"errmsg" : "Collection already exists. NS: hrm.mycol",
"code" : 48,
"codeName" : "NamespaceExists"
>
在 MongoDB 中,你不需要创建集合,当你插入一些文档时,MongoDB 会自动创建集合。
> db.mycol2.insert("name" : "mongdb")
> show collections
mycol2
...
3.3.删除集合
删除集合使用db.collection.drop()
,如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
> use hrm
switched to db hrm
> show tables
mycol
role
user
> db.user.drop()
true
4.文档操作
4.1.插入文档
MongoDB 使用 db.collection.insert
,db.collection.insertOne
或 db.collection.save
方法向集合中插入文档,语法`
db.COLLECTION_NAME.insert(document)
或
db.COLLECTION_NAME.save(document)
- save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
- insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
在 3.2 版本后还有以下几种语法可用于插入文档:
- db.collection.insertOne():向指定集合中插入一条文档数据
- db.collection.insertMany():向指定集合中插入多条文档数据
db.collection.insertOne() 用于向集合插入一个新文档,语法格式如下:
db.collection.insertOne(
<document>,
writeConcern: <document>
)
db.collection.insertMany() 用于向集合插入一个多个文档,语法格式如下:
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
writeConcern: <document>,
ordered: <boolean>
)
参数说明:
- document:要写入的文档。
- writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
- ordered:指定是否按顺序写入,默认 true,按顺序写入。
实例:给user集合插入document
> var document = db.user.insertOne("a": 3) //给user集合插入数据,并保持结果到document变量
> document //打印document变量
"acknowledged" : true,
"insertedId" : ObjectId("605d8a844d99251c4e70bd60")
>db.user.find(); //查找user集合中的document
注意:如果没指定 “_id”属性,就会自动生成一个随机ID。
实例:给 user 集合批量插入数据
> var res = db.user.insertMany(["b": 3, 'c': 4])
> res
"acknowledged" : true,
"insertedIds" : [
ObjectId("605d8aec4d99251c4e70bd63"),
ObjectId("605d8aec4d99251c4e70bd64")
]
>
4.2.更新文档
使用 db.collection.update
方法更新已存在的文档。语法格式如下:
db.collection.update(
<query>,
<update>,
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
)
参数说明:
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如 , , ,inc…)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
实例:修改指定文档
> db.user.insertOne(username:"zs",id:"1",age:18); //添加一个文档
"acknowledged" : true,
"insertedId" : ObjectId("605d927e4d99251c4e70bd67")
> db.user.update(username:"zs",$set:title:"ls"); //匹配username为 zs的文档,把username修改为ls
WriteResult( "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 )
> db.user.find().pretty(); //查找user下的所有文档,pretty是进行格式化
"_id" : ObjectId("605d927e4d99251c4e70bd67"),
"username" : "zs",
"id" : "1",
"age" : 18,
"title" : "ls"
解释:db.user.update(username:“zs”,$set:title:“ls”);
- username:“zs” :为第一个参数,对应query,满足该条件才会修改
- $set:title:“ls” :为第二个参数,把 title设置为 ls , 默认只会修改第一条
如果要修改所有文档把multi改为true
db.user.update(username:"zs",$set:title:"ls" , false, true);
- 第三个参数fase:对应upsert,意思是不存在就插入数据
- 第四个参数true:对应multi,修改所有username为zs的文档把title修改为ls
注意:update只能修改文档中已经存在的属性
另外我们也可以使用 db.集合.save来更新文档,如:
> db.user.save(
"_id" : ObjectId("605d927e4d99251c4e70bd67"),
"username" : "ww", //username做了值的修改
"age" : 18,
"title" : "ls"
); //注意:这里我少写了一个id字段
> db.user.find().pretty();
"_id" : ObjectId("605d927e4d99251c4e70bd67"),
"username" : "ww",
"age" : 18,
"title" : "ls"
这里的username确实被更新了,对于id字段由于我save的时候没有指定,所以最终就没有id字段了,也就是说这种更新相当于是把之前的文档干掉,保存新的文档进去。
4.3.删除文档
MongoDB中 remove() 函数是用来移除集合中的数据。格式如(2.6 版本以后的):
db.collection.remove(
<query>,
justOne: <boolean>,
writeConcern: <document>
)
参数说明:
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
- writeConcern :(可选)抛出异常的级别。
实例:插入3条username:zs的数据,然后再根据username:zs来删除
> db.user.insertOne(username:"zs",id:"1",age:18);
"acknowledged" : true,
"insertedId" : ObjectId("605d97224d99251c4e70bd68")
> db.user.insertOne(username:"zs",id:"2",age:19);
"acknowledged" : true,
"insertedId" : ObjectId("605d97224d99251c4e70bd69")
> db.user.insertOne(username:"zs",id:"3",age:20);
"acknowledged" : true,
"insertedId" : ObjectId("605d97234d99251c4e70bd6a")
> db.user.find(); //现在有3个文档,username都是zs
"_id" : ObjectId("605d97224d99251c4e70bd68"), "username" : "zs", "id" : "1", "age" : 18
"_id" : ObjectId("605d97224d99251c4e70bd69"), "username" : "zs", "id" : "2", "age" : 19
"_id" : ObjectId("605d97234d99251c4e70bd6a"), "username" : "zs", "id" : "3", "age" : 20
> db.user.remove(username:"zs",1); //删除1条,username为zs的文档
> db.user.find().pretty(); //查找user集合中的文档 ,只剩下2个了
"_id" : ObjectId("605d97224d99251c4e70bd69"), "username" : "zs", "id" : "2", "age" : 19
"_id" : ObjectId("605d97234d99251c4e70bd6a"), "username" : "zs", "id" : "3", "age" : 20
> db.user.remove(username:"zs"); //这一次并没有指定justOne为1,会删除所有
WriteResult( "nRemoved" : 2 )
> db.user.find(); //再执行find,发现所有的username为zs的都删除了
如果想删除集合中的所有数据可以使用如下命令:
db.user.remove()
4.4.查询文档
基本查询语法
MongoDB 查询数据的语法格式如下:
db.collection.find(query, projection)
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
> db.collection.find().pretty()
pretty() 方法以格式化的方式来显示所有文档
> db.user.find();
"_id" : ObjectId("605d9a0b4d99251c4e70bd6d"), "username" : "zs", "id" : "1", "age" : 18
"_id" : ObjectId("605d9a0b4d99251c4e70bd6e"), "username" : "zs", "id" : "2", "age" : 19
"_id" : ObjectId("605d9a0c4d99251c4e70bd6f"), "username" : "zs", "id" : "3", "age" : 20
> db.user.find().pretty();
"_id" : ObjectId("605d9a0b4d99251c4e70bd6d"),
"username" : "zs",
"id" : "1",
"age" : 18
"_id" : ObjectId("605d9a0b4d99251c4e70bd6e"),
"username" : "zs",
"id" : "2",
"age" : 19
"_id" : ObjectId("605d9a0c4d99251c4e70bd6f"),
"username" : "zs",
"id" : "3",
"age" : 20
>
除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档。
> db.user.findOne();
"_id" : ObjectId("605d999c4d99251c4e70bd6b"), "a" : 3
在查找文档的过程中我们通常会增加查询条件,通过下表可以更好的理解 MongoDB 的条件语句查询:
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | <key>:<value> | db.col.find("by":"mongdb").pretty() | where by = 'mongdb' |
小于 | <key>:$lt:<value> | db.col.find("likes":$lt:50).pretty() | where likes < 50 |
小于或等于 | <key>:$lte:<value> | db.col.find("likes":$lte:50).pretty() | where likes <= 50 |
大于 | <key>:$gt:<value> | db.col.find("likes":$gt:50).pretty() | where likes > 50 |
大于或等于 | <key>:$gte:<value> | db.col.find("likes":$gte:50).pretty() | where likes >= 50 |
不等于 | <key>:$ne:<value> | db.col.find("likes":$ne:50).pretty() | where likes != 50 |
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。语法格式如下:
db.col.find(key1:value1, key2:value2).pretty()
实例:查找username为zs,id为1的文档
> db.user.find(username:"zs",id:"2");
"_id" : ObjectId("605d9a0b4d99251c4e70bd6e"), "username" : "zs", "id" : "2", "age" : 19
以上实例中类似于 WHERE 语句:where username=‘zs’ AND id=‘2’
去重distinct
语法 db.user.distinct(“属性”)
> db.usertable.distinct("username")
[ "zs" ]
or 和 and 语法
MongoDB 支持 ,or ,and ,not 运算,分别对应关键字 o r ( 或 者 ) , or(或者), or(或者),and(并且) , $not(取反) ,语法格式如下:
>db.col.find(
$or: [
key1: value1, key2:value2
]
).pretty()
实例:查找username为zs 或者 id 为2的文档
> db.user.find($or:[ username:"zs","id":2 ]);
"_id" : ObjectId("605d9a0b4d99251c4e70bd6d"), "username" : "zs", "id" : "1", "age" : 18
"_id" : ObjectId("605d9a0b4d99251c4e70bd6e"), "username" : "zs", "id" : "2", "age" : 19
"_id" : ObjectId("605d9a0c4d99251c4e70bd6f"), "username" : "zs", "id" : "3", "age" : 20
>
实例:查找username为zs and id为2的文档
> db.user.find("username":"zs","id":2);
上面语法等同于
> db.user.find($and:[ username:"zs","id":2 ]);
以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: ‘where age >17 AND (id = 1 OR id = 2)’
> db.user.find(age:$gt:17,$or:[id:"1",id:"2"])
"_id" : ObjectId("605d9a0b4d99251c4e70bd6d"), "username" : "zs", "id" : "1", "age" : 18, "title" : "ls"
"_id" : ObjectId("605d9a0b4d99251c4e70bd6e"), "username" : "zs", "id" : "2", "age" : 19
取模运算
MongoDB支持取模运算,类似:where id % 2 = 1
db.user.find("_id":"$mod":[2,1])
in和nin
成员运算符 in和not in ,在Mongdb中通过$in , $nin
实现 ,类似于 where age in (1,2,3)
> db.user.find("age":"$in":[1,2,3])
条件操作符号
MongoDB中条件操作符有:
- (!=) 不等于 - $ne
- (>) 大于 - $gt
- (<) 小于 - $lt
- (>=) 大于等于 - $gte
- (<= ) 小于等于 - $lte
如果你想获取 “user” 集合中 “age” 大于 18 的数据,你可以使用以下命令:
db.user.find(age : $gt : 18)
如果你想获取"user"
以上是关于三.MongoDB入门-Mongodb的CRUD的主要内容,如果未能解决你的问题,请参考以下文章