MongoDB基本概念
MongoDB基本概念
和传统数据库对比
不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下面我们挨个介绍,下表将帮助您更容易理解Mongo中的一些概念:
对比项 | mongo | 数据库 |
---|---|---|
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
通过下图实例,我们也可以更直观的了解Mongo中的一些概念:
数据逻辑层次关系:文档=>集合=>数据库\
下面我们对里面的每一个概念进行详细解释
数据库
一个mongoDB的实例可以运行多个database,database之间是完全独立的,每个database有自己的权限,每个database存储于磁盘的不同文件。
命令规范
databases的name可以是任意的UTF-8字符串。但是有以下限制
- 空字符串””是非法的
- 不允许出现’’,.,$,/,,\0字符
- 建议名称都是小写
- 不能超过64个字节
特殊数据库
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
- admin:它是root级别的数据库,如果一个用户创建了admin数据库,该用户将自动集成所有数据库的权限,它可以执行一些服务器级别的命令,如列出所有数据库、关闭服务等。
- local:该数据库将永远不能被复制,只能在单台服务器本地使用。
- config:存储分布式部署时shard的配置信息
数据库操作
查看数据库列表
show dbs
命令可以显示所有数据的列表
1 | show dbs; |
显示当前数据库
执行 “db” 命令可以显示当前数据库对象或集合。
1 | db |
创建数据库
MongoDB 使用 use 命令创建数据库,如果数据库不存在,MongoDB 会在第一次使用该数据库时创建数据库。如果数据库已经存在则连接数据库,然后可以在该数据库进行各种操作。
1 | show dbs; |
注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。
1 | use tmpdb; |
现在
tmpdb
数据库就显示出来了
删除数据库
可以使用
db.dropDatabase()
删除数据库
1 | show dbs; |
集合
相当于关系数据库的表,不过没有数据结构的定义。它有多个document组成。
命令规范
因为是无结构定义的,所以你可以把任何document存入一个collection里。每个collection用一个名字标识,需要注意以下几点:
- 名字不允许是空字符串””
- 名字不能包含\0字符,因为它表示名字的结束
- 不能创建以system.开头的
集合操作
创建集合
可以通过
db.createCollection(name,option)
创建集合参数说明:
- name: 要创建的集合名称
- options: 可选参数, 指定有关内存大小及索引的选项
1 | 创建或选择tmpdb数据库 |
查看集合
如果要查看已有集合,可以使用 show collections 或 show tables 命令:
1 | show collections; |
删除集合
MongoDB 中使用 drop() 方法来删除集合
db.collection.drop()
如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
从结果中可以看出 所有的集合已被删除。
日期
表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。
1 | var mydate1 = new Date() //格林尼治时间 |
1 | var mydate2 = ISODate() //格林尼治时间 |
这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。
返回一个时间类型的字符串:
1 | var mydate1str = mydate1.toString() |
或者
1 | Date() |
文档
mongoDB的基本单位,相当于关系数据库中的行,它是一组有序的key/value键值对,使用json格式,如:{“foo” : 3, “greeting”: “Hello, world!”}。
key的命令规范
key是个UTF-8字符串,以下几点是需要注意的地方:
- 不能包含\0字符(null字符),它用于标识key的结束
- .和$字符在mangodb中有特殊含义,如$被用于修饰符($inc表示更新修饰符),应该考虑保留,以免被驱动解析
- 以_开始的key也应该保留,比如_id是mangodb中的关键字
注意事项
在mangodb中key是不能重复的
value 是弱类型,甚至可以嵌入的一个document
key/value键值对在mangodb中是有序的
mangodb是类型和大小写敏感的,如{“foo” : 3}和{“foo” : “3”}是两个不同的document,{“foo” : 3}和{“Foo” : 3}类
文档基础使用
MongoDB最主要是对文档的操作,下面我们来学习以下文档的操作
插入文档
MongoDB插入数据有多种形式,下面我们来一一学习
insert(不推荐)
插入一条或多条数据需要带有允许插入多条的参数,这个方法目前官方已经不推荐了
注意:若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
1 | db.blog.insert({ |
如果没有添加
_id
参数会自动生成_id
值的,也可以自定义指定_id
1 | db.blog.insert({ |
如果
_id
重复会抛出异常
insertOne(推荐)
官方推荐的写法,向文档中写入一个文档
1 | db.blog.insertOne({ |
这样就将数据插入到mongoDB中了
insertMany(推荐)
该语句是进行批量插入的,可以直接进行批量插入
1 | db.blog.insertMany([{ |
这样就将多个文档插入到MongoDB中了
查询文档
查询所有文档
find
方法用于更新已存在的文档,MongoDB 查询数据的语法格式如下
1 | db.blog.find(); |
这样就将所有的数据查询出来了
格式化文档
这样看起来不太美观,可以通过
pretty
进行格式化
1 | db.blog.find().pretty(); |
经过格式化这样看起来就好看多了
只返回一个文档
find();
是返回所有的文档,如果想要只返回第一个文档可以使用findOne()
1 | db.blog.findOne(); |
注意:findOne自动带有格式化效果,不需要在加上pretty
方法了
等值查询
我们查询
blog
表中title='MySql 教程2'
的数据
1 | db.blog.find({"title":"MySql 教程2"}).pretty(); |
这样我们就将数据给查询出来了
投影
projection
选择可以控制某一列是否显示,语法格式如下
find({},{"title":1})
其中如果
title
是1
则该列显示,否则不显示
1 | 只显示title列的数据 |
注意在一个查询中,投影列的状态必须是一致的,如果不一致将会报错
1 | 显示 title 不显示description列的数据 |
更新文档
update更新
update() 方法用于更新已存在的文档,更新的时候需要加上关键字
$set
1 | db.blog.update({"_id":"1"},{$set:{'likes',666}}) |
和普通的SQL的对应关系如下
执行完成后查询,我们发现数据已经更新了
save更新
save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插
1 | db.blog.save({ |
如果
_id
不存在则进行插入操作
如果_id
存在则更新数据
1 | db.blog.save({ |
删除文档
条件删除文档
remove() 方法可以删除文档
1 | db.blog.remove({"_id":"1"}) |
这样是删除
_id
是1的数据
我们看到数据已经被删除了,我们可以不加条件删除多个文档
1 | db.blog.remove({}); |
这样就删除了所有的文档
只删除第一个文档
remove({})方法可以删除所有问题,如果我们只要删除符合条件的第一个文档
准备数据
我们插入多条数据,这里用到了mongodb shell,后面我们会讲到
1 | for(var i=0;i<10;i++){ |
这样我们就连续插入了10条数据
remove方式删除
可以使用
justOne
参数,默认是true,删除所有符合条件的数据,如果是false 则只删除符合条件的第一个文档
1 | db.blog.remove({},true); |
这样就把第一个
_id
为0
的数据给删除了
delete删除文档
方推荐使用 deleteOne() 和 deleteMany() 方法删除文档
删除单个文档
deleteOne
只会删除符合条件的第一个文档,和remove({},true)
效果一致
1 | db.blog.deleteOne({}); |
我们看到只删除了一个文档
批量删除文档
deleteMany
可以进行批量删除文档,和remove({})
效果一致
1 | db.blog.deleteMany({}); |
这样就把文档全部删除了
元数据
数据库的信息是存储在集合中。它们使用了系统的命名空间:
1 | dbname.system.* |
在MongoDB数据库中名字空间 <dbname>.system.* 是包含多种系统信息的特殊集合(Collection),如下:
集合命名空间 | 描述 |
---|---|
dbname.system.namespaces | 列出所有名字空间。 |
dbname.system.indexes | 列出所有索引。 |
dbname.system.profile | 包含数据库概要(profile)信息。 |
dbname.system.users | 列出所有可访问数据库的用户。 |
dbname.local.sources | 包含复制对端(slave)的服务器信息和状态。 |
对于修改系统集合中的对象有如下限制。
在插入数据,可以创建索引。但除此之外该表信息是不可变的(特殊的drop index命令将自动更新相关信息)。
是可修改的。 是可删除的。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 | 正则表达式类型。用于存储正则表达式。 |
下面说明下几种重要的数据类型。
ObjectId
ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
- 前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
- 接下来的 3 个字节是机器标识码
- 紧接的两个字节由进程 id 组成 PID
- 最后三个字节是随机数
MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象
由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:
1 | var newObject = ObjectId() |
ObjectId 转为字符串
1 | newObject.str |