三.MongoDB入门-Mongodb的CRUD

Posted 墨家巨子@俏如来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三.MongoDB入门-Mongodb的CRUD相关的知识,希望对你有一定的参考价值。

1.MongDB核心概念

mongodb是最像关系型数据库的非关系数据库,其中很多思想和关系数据库很像,在mongodb中有几个核心概念:文档、集合、数据库如下:

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary 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 非常突出的特点。

需要注意的是:

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意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 collectionsshow 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.insertdb.collection.insertOnedb.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的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data MongoDB 一:入门篇(环境搭建简单的CRUD操作)

mongodb的CRUD操作三

《MongoDB入门教程》第06篇 CRUD之创建文档

《MongoDB入门教程》第06篇 CRUD之创建文档

《MongoDB入门教程》第06篇 CRUD之创建文档

《MongoDB入门教程》第14篇 CRUD之更新文档