MongoDB 之基础入门一
本文主要介绍 MongoDB 数据库的概念以及基本应用,采用“CentOS Linux release 7.6.1810 (Core)”的 Linux 版本作为 MongoDB 的安装系统。主要包括以下内容:
1. MongoDB 简介
2. MongoDB 的安装与配置
3. MongoDB 的体系结构
4. 使用 mongo shell
5. CRUD 操作
1. MongoDB 简介
MongoDB 是一个基于分布式文件存储、文档型的 NoSQL 数据库。
什么是文档型数据库?
Mongo 的文档是 BSON 文档,就是一个 JSON 二进制的文档。
Mongo 与关系型数据库存储的本质区别,如图:
相比关系型数据库,这样存储就大大提高了查询效率。
2. MongoDB 的安装与配置
1) MongoDB 的安装
1. 上传“mongodb-linux-x86_64-4.0.10.tgz”安装包到 Linux 服务器。
2. 关闭 Linux 的防火墙。
3. 创建 MongoDB 解压路径
mkdir /usr/local/mongodb
4. 解压 MongoDB
tar -zxvf mongodb-linux-x86_64-4.0.10.tgz -C /usr/local/mongodb/
2) MongoDB 的配置
1. 设置环境变量(保证在任何目录下都可以执行 MongoDB 命令)
1) 编辑“bash_profile”文件
vi ~/.bash_profile
2) 添加环境变量,保存退出
Red Hat 采用如下配置:
MONGODB_HOME=/usr/local/mongodb/mongodb-linux-x86_64-4.0.10
export MONGODB_HOME
PATH=MONGODB_HOME/bin:$PATH
export PATH
CentOS 采用如下配置:
export MONGODB_HOME=/usr/local/mongodb/mongodb-linux-x86_64-4.0.10
export PATH=$PATH:$MONGODB_HOME/bin
2. 生效环境变量
source ~/.bash_profile
3. 输入“mongo”,按两次“Tab键”可查看所有的 MongoBD 命令。
4. 启动 MongoDB
mongod 或者 mongod –-dbpath /data/db
1) Red Hat 可能出现以下错误:
在 MongoDB 需要依赖RPM 包,所以还要安装 RPM 包。
2) CentOS 可能出现以下异常:
以上错误表示没有找到 MongoDB 数据保存的默认目录“/data/db”,所以创建该目录即可:mkdir /data/db
3) 查看到如下内容表示启动成功
4) 或者使用“netstat -tunpl | grep 27017”查看
3. MongoDB 的体系结构
1) MongoDB Server
它是一个实例多个数据库结构体系,它们的关系是一对多(1:N)。
2) 存储结构
1. 逻辑存储结构
数据库(database)、表(集合 Collection)、记录、(文档 Document)
2. 物理存储结构
1) –-dbpath /data/db 指定数据库文件存储的位置
2) MongoDB 的物理存储的文件
1. 命名空间文件,后缀:*.ns,大小:16M,主要记录命名空间的信息。
2. 数据文件:后缀:*.0, *.1, *.2,***,大小:0 -> 16M,如果满了 1 -> 32M, 如果也满了 2 -> 64M(一次类推),最大的文件大小为2G。这样的好处是牺牲存储的空间,提高时间,也就是性能。
3. 日志文件,存储的位置可能不一样
1) 直接存储在操作系统中,也就是 /data/db 目录下。
1. 系统日志文件:记录的是系统的启动信息,警告信息等。
2. journal日志文件:重做日志,即:redo日志,用于恢复。
2) 存储在集合(Collection)中
1. oplog:复制操作的日志,只记录主从复制的日志。
2. 慢查询的日志(需要单独配置),一般在生产系统中,记录大于200毫秒的日子。
3) 注意:
1. 从3.2版本后,MongoDB 的默认数据引擎就改为了wiredTiger,所以在/data/db 目录下就没有了(如:*.ns)的文件了。在早起的版本中,是采用内存映射的数据引擎就有这些文件。可以指定参数改为“内存引擎”:--storageEngine=mmapv1
2. 新版本的数据文件大小是从 64M 开始的。
4. 使用 mongo shell
mongo shell 就是 MongoDB 命名行的操作工具。
1) 启动 mongo shell
1. 输入“mongo”命令就可以进入 mongo shell 了。
2. 参数: --username 用户名
--password 密码
--host 主机
--port 端口号
参数简写:mongo -u *** -p *** -host *** -port ***
3. 查看mongo shell 帮助命令
mongo shell -help
4. mongo shell 使用外部编辑器:vi
1. 定义环境变量
export EDITOR=vi
2. 比如定义个函数:function myfunction1(){}
3. 编辑该函数:edit myfunction1
4. 后面直接输入函数名,就可以查看改函数的定义。
2) 使用启动配置文件.mongorc.js
当启动 mongo shell 时就会读取.mongosc.js 文件中的内容。
1. 当启动了mongo shell 命令提示符后,就会在当前用户的家目录下生成一个.mongorc.js文件,查看该文件输入:ls -a 命令
2. 查看.mongorc.js 内容
more .mongorc.js
3. 示例:
1) 示例一,显示当期发出命令的数量
1. 编辑.mongorc.js 文件,添加如下内容:
cmdCount = 1;
prompt = function() {
return "mongo " + (comCount++) + ">";
}
2. 启动mongo shell 就会看到如下内容:
mongo 1>
mongo 2>
2) 示例二,显示数据库的名称和主机名称
1. 编辑.mongorc.js 文件,修改为如下内容:
host = db.serverStatus().host;
cmdCount = 1;
prompt = function() {
return db + "@" + host+" " + (cmdCount++) + ">";
}
2. 启动mongo shell 就会看到如下内容:
test@localhost.localdomain 1>
test@localhost.localdomain 2>
3) mongo shell 的基本操作
1. 启动 MongoDB Server 命令
mongod
2. 连接 MongoDB 客户端
mongo
3. 退出 Mongo Server
quit() 或者 exit
4. 查看MongoDB Server 已存在的数据库
show dbs
5. 创建数据库
use mydemo #选择mydemo 数据库
db.test1.insertOne({x:1}) #插入数据才开始创建mydemo 数据库
6. 查看当前数据库中的表
show tables 或者show collenctions
4) mongo shell 中的数据类型
由于 MongoDB 底层采用的是 Java Script,所以与 JavaScript 的数据类型也非常相似。数据类型包括:字符串、整型、布尔类型、浮点型、时间类型等。
1. 日期类型:data
创建日期类型的几种方式:
1) Date(): 值为当期时间,插入的是一个字符串类型。
2) New Date(): 值为格林威治标准时间,插入的是isodate 类型。
3) ISODate(): 类似 New Date() 的方式。
2. ObjectId:当插入数据的时候,如果没有指定“_id”字段,自动生成一个字段“_id”,该字段相当于主键,是一个是12字节的BSON 类型的字符串,长度为24,例如:
{ "_id" : ObjectId("5d05f158bf34e927677c3e29"), "x" : 1 }
3. 数字类型
1) NumberInt: 表示32位的整数
2) NumberDecimal: 表示34位的小数
3) Double: 与其他编程语言一样,如果数字类型没有指定类型,默认为该类型。
4) 数据类型需要注意的问题:
1. 添加测试数据
db.test2.insertOne({"_id": 1, "val": NumberDecimal("9.99"), "description": "Decimal"})
db.test2.insertOne({"_id": 2, "val": 9.99, "description": "Double"})
db.test2.insertOne({"_id": 3, "val": 10, "description": "Double"})
db.test2.insertOne({"_id": 4, "val": NumberLong(10), "description": "Long"})
db.test2.insertOne({"_id": 5, "val": NumberDecimal("10.0"), "description": "Decimal"})
2. 查询
1) 条件:{"val":9.99}
mydemo1@localhost.localdomain 8>db.test2.find({"val":9.99})
{ "_id" : 2, "val" : 9.99, "description" : "Double" }
只会匹配到1条,因为数字类型默认是 Double 类型。
2) 条件:{"val":NumberDecimal("9.99")}
mydemo1@localhost.localdomain 12>db.test2.find({"val":NumberDecimal("9.99")})
{ "_id" : 1, "val" : NumberDecimal("9.99"), "description" : "Decimal" }
3) 条件:{"val":10}
mydemo1@localhost.localdomain 13>db.test2.find({"val":10})
{ "_id" : 3, "val" : 10, "description" : "Double" }
{ "_id" : 4, "val" : NumberLong(10), "description" : "Long" }
{ "_id" : 5, "val" : NumberDecimal("10.0"), "description" : "Decimal" }
会匹配到3条数据,因为对于整型10的匹配,将匹配所有数据类型为10的数据。
4) 条件:{"val":NumberDecimal("10")}
mydemo1@localhost.localdomain 14>db.test2.find({"val":NumberDecimal("10")})
{ "_id" : 3, "val" : 10, "description" : "Double" }
{ "_id" : 4, "val" : NumberLong(10), "description" : "Long" }
{ "_id" : 5, "val" : NumberDecimal("10.0"), "description" : "Decimal" }
也会匹配3条数据,只要值为10的数据。
5) 使用 MongoDB Web 控制台
在启动 MongoDB 时指定参数:--httpinterface
5. CRUD 操作
删除表:db.emp.drop()
1) 插入文档
insert 如果在插入数据的时候,collection 不存在会自动创建该集合,插入数据的几种方式:
1. insertOne() 插入一条数据,例如:
db.student1.insertOne({"_id":"stu001", "name":"Tome", "age":25, "grade": {"chinese":80, "math":90, "english":88}})
2. insertMany() 插入多条数据,接受一个数组,例如:
db.student1.insertMany([{"_id":"stu002", "name":"Mary", "age":23, "grade": {"chinese":80, "math":90}}, {"_id":"stu003", "name":"Mike", "age":25, "grade": {"chinese":81, "math":90, "english":88}}])
3. insert() 插入一条或多条数据,是insertOne() 与insertMany() 的结合,例如:
db.student1.insert([{"_id":"stu004", "name":"Abc", "age":31, "grade": {"chinese":99, "math":88}}])
2) 查询文档
1. 基本查询
1) 查询所有的员工信息
db.emp.find()
2) 查询职位为经理的员工
db.emp.find({"job":"MANAGER"})
3) 操作符:$in、$or
查询职位是 MANAGER 或者是 CLERK 的员工信息
db.emp.find({"job":{$in:["MANAGER", "CLERK"]}})
或者使用$or 运算符
db.emp.find({$or:[{"job":"MANAGER"}, {"job":"CLERK"}]})
4) 操作符:$gt、$lt、$eq
1. 查询10号部门工资大于2000的员工
db.emp.find({"deptno":10, "sal":{$gt:2000}})
2. 查询10号部门工资小于2000的员工
db.emp.find({"deptno":10, "sal":{$lt:2000}})
3. 查询10号部门的员工
db.emp.find({"deptno":{$eq:10}})
或者
db.emp.find({"deptno":10})
2. 查询嵌套的文档
1) 查询语文81分、数学90分、英语88分的文档
db.student2.find({"grade":{"chinese":81, "math":90, "english":88}})
注意:查询嵌套的文档,必须指定每一个 field,且顺序必须保持与原文档一致。
2) 查询嵌套文档中的一个列,例如:查询数学成绩为82分的文档
db.student2.find({"grade.math":82})
3) 使用比较运算符,查询英语成绩大于88分的文档
db.student2.find({"grade.english":{$gt:88}})
4) 使用 AND 运算符,查询语文成绩大于88分,并且英语成绩小于90分的文档
db.student2.find({"grade.chinese":{$gt:88},"grade.english":{$lt:90}})
3. 查询数组的文档
1) $all运算符,查询所有包含 Hadoop 和 Java 的文档
db.studentbook.find({"books":{$all:["Hadoop","Java"]}})
4. 查询数组中嵌套的文档
1) 查询 Java 有4本的文档
db.studentbook1.find({"books":{"bookname":"Java", "quantity":4}})
2) 指定查询的条件,查询数组中第一个元素大于3本的文档
db.studentbook1.find({"books.0.quantity":{$gt:3}}) #0表示第一个元素,1表示第二个元素,以此类推
3) 查询数组中至少有一个quantity 的值大于3的文档
db.studentbook1.find({"books.quantity":{$gt:3}})
4) $elemMatch 运算符匹配多个条件。
查询有 Java 的书,并且数量等于4本的文档
db.studentbook1.find({"books":{$elemMatch:{"bookname":"Java", "quantity":4}}})
5. 查询空值(null)或者缺失的列
1) 查询值为null 的文档
db.student3.find({"age":null}) #定义列为 null 值或者未定义age 列都将返回
2) $type 运算符,查询只返回值null 的记录
db.student3.find({"age":{$type:10}}) #BSON 使用10表示null 值
3) $exists 运算符,检查是否缺失某个列
db.student3.find({"age":{$exists:false}}) #fasle: 表示查询不存在age 列的文档,true: 表示存在的。
6. 使用游标
在使用find() 语句查询时,将返回一个游标,我们可以使用这个游标操作文档。
db.collection.find() 返回一个游标(cursor),如果使用cursor 访问文档,使用迭代器,默认每次返回20条文档。
1) 基本使用
1. 定义游标
var mycursor = db.emp.find()
2. 调用游标
mycursor
2) 使用游标访问文档
var mycursor = db.emp.find()
while(mycursor.hasNext()){
printjson(mycursor.next())
}
3) 游标和数组(以下语句逐条执行)
var mycursor = db.emp.find()
var myarray = mycursor.toArray()
var mydoc = myarray[3]
mydoc
4) 使用skip()、limit() 方法,实现分页查询
第一页:var mycursor = db.emp.find().limit(5)
第二页:var mycursor = db.emp.find().skip(5).limit(5)
3) 更新文档
$set 运算符,用于更新文档;
$inc 运算符,在原值基础上加指定的值。
1. updateOne()
将"_id"为7839的薪水更新为8000
db.emp.updateOne({"_id":7839}, {$set:{"sal":8000}})
2. updateMany()
将10号部门的薪水加100
db.emp.updateMany({"deptno":{$eq:10}}, {$set:{"sal":"sal"+100}}) #结果更新成了"sal100",显然这不对的
db.emp.updateMany({"deptno":{$eq:10}}, {$inc:{"sal":100}}) #正确
3. 更新文档的相关参考
https://docs.mongodb.com/manual/reference/method/db.collect
ion.updateOne/#db.collection.updateOne
https://docs.mongodb.com/manual/reference/method/db.collect
ion.updateMany/#db.collection.updateMany
https://docs.mongodb.com/manual/reference/method/db.collect
ion.replaceOne/#db.collection.replaceOne
4) 删除文档
1. deleteOne()
删除"_id"为7839的员工
db.emp.deleteOne({"_id":7839})
2. deleteMany()
删除所有的10号部门员工
db.emp.deleteMany({"deptno":10})
5) 批处理操作
为了提高效率,使用 db.collection.bulkWrite() 方法,将一组命令一起执行, 支持:insert、update、delete, 同时也支持insertMany 等。
1. 创建 mystudents 表,并批处理插入3条数据、更新1条数据、删除一条数据,例如:
db.mystudents.bulkWrite([
{insertOne:{"document":{"_id":101,"name":"Tom","age":25}}},
{insertOne:{"document":{"_id":102,"name":"Mary","age":28}}},
{insertOne:{"document":{"_id":103,"name":"Abeam","age":31}}},
{updateOne:{"filter":{"_id":101}, "update":{$set:{"name":"To"}}}},
{deleteOne:{"filter":{"_id":102}}}
])