person

MongoDB 简介

MongoDB 是为快速开发互联网 WEB 应用而设计的数据库系统。MongoDB 的设计目标是极简、灵活、作为 WEB 应用栈的一部分。MongoDB 的数据模型是面向文档的,所谓文档是一种类似于 JSON 的结构(BJSON,二进制的 JSON),简单理解 MongoDB 这个数据库中存的是各种各样的 JSON。

MongoDB 安装

1、下载地址:MongoDB 安装包下载

2、配置环境变量:将 C:\Program Files\MongoDB\Server\3.2\bin 添加到环境变量中;

3、在 C 盘根目录 创建 data 文件夹,并在 data 文件夹中创建 db 文件夹,即 C:\data\db(可通过 ` mongod --dbpath C:UserslilichaoDesktopmongodatadb --port 123
` 修改默认数据库存储文件夹和端口);

4、cmd 中输入 mongod 启动 MongoDB 服务;

5、打开新的 cmd 端口,输入 mongo 连接数据库。

配置 MongoDB 服务自启动

1、在 data 文件夹下创建 log 文件夹,创建日志文件 mongod.log

2、以管理员身份启动 cmd,输入:

mongod --dbpath=C:\data\db --logpath=C:\data\log\mongod.log --install --serviceName="MongoDB"

看到类似:

2019-11-18T10:17:45.206+0800 I CONTROL  [main] log file "C:\data\log\mongod.log" exists; moved to "C:\data\log\mongod.log.2019-11-18T02-17-45".

说明服务安装成功。

3、此电脑(右键)→管理→服务和应用程序→服务 找到 MongoDB 服务启动。

MongoDB 基本操作

基本概念

数据库(database):

数据库是一个仓库,在仓库中可以存放集合。

集合(collection):

集合就是一组文档,也就是集合是用来存放文档的。

文档(document):

文档数据库中的最小单位,我们存储和操作的内容都是文档, 在MongoDB中每一条数
据都是一个文档。

  • 多个文档组成集合,多个集合组成数据库。

基本指令

在MongoDB中,数据库和集合都不需要手动创建,当我们创建文档时,如果文档所在的集合或数据库不存在会自动创建数据库和集合。

  • show databases:显示当前所有数据库;
  • use 数据库名称:进入到指定数据库;
  • db:显示当前所处数据库;
  • show collections:显示当前数据库所有的集合。

数据库的 CRUD

增加(Create)

db.<collection>.insert()

插入单个文本

db.student.insert({
    name: "张三", age: 12
});

插入多个文本

db.student.insert([
    {name: "婉儿", age: 12},
    {name: "李四", age: 25},
    {name: "王五", age: 19}
]);

读取(Read)

查询一个

db.<collection>.findOne()

db.student.findOne({name: "张三"});

查询所有

db.<collection>.find()

db.student.find();

查询符合条件的所有文档:

db.student.find({age: 12});

多条件查询

db.student.find({
    name: "张三", age: 12
});

查询记录条数

db.student.find().count();

## 更新(Update)

db.<collection>.update()

更新单个文档

db.student.update(
    {name: "张三"},
    {
        $set: {
            age: 30,
            gender: "男"
        }
    }
);
  • 文档中没有的字段会自动添加

更新多个文档

db.student.update(
    {age: 12},
    {
        $set: {
            age: 30,
            gender: "男"
        }
    },
    {
        multi: true
    }
);

删除字段

db.student.update(
    {age: 30},
    {
        $unset: {
            gender: "男"
        }
    },
    {
        multi: true
    }
);

删除(Delete)

db.<collection>.remove()

默认情况下删除匹配条件的所有文档

db.student.remove({age: 30});

只删除一个

db.student.remove({age: 30}, true);

清空集合

db.student.remove({});

删除集合

db.student.drop();

删除数据库

db.dropDatabase();

sort 和投影

sort

sort() 用来指定文档的排序规则,需要传递一个对象来指定排序规则。

// 1 表示升序,-1 表示降序
db.emp.find().sort({sal: 1});

投影

// find() 的第二个参数设置投影,下面的语句查询结果只显示 ename, sal(_id默认显示,设为 0 表示不显示)
db.emp.find({}, {ename: 1, sal: 1, _id: 0});

Mongoose

一个让我们可以通过 Node 来操作 MongoDB 的模块。

优势

  • 可以为文档创建一个模式结构(Schema,也可以称为约束)
  • 可以对模型中的对象/文档进行验证
  • 数据可以通过类型转换转换为对象模型
  • 可以使用中间件来与应用业务逻辑挂钩
  • 比 Node 原生的 MongoDB 驱动更易于使用

mongoose 提供的对象

  • Schema

    • Schema 对象定义约束了数据库中的文档结构
  • Model

    • Model 对象作为集合中所有文档的表示,相当于 MongoDB 数据库中的集合 collection
  • Document

    • Document 表示集合中的具体文档

Schema 和 Model 的使用

// 1、下载 mongoose => npm i mongoose --save
// 2、引入 mongoose
var mongoose = require("mongoose");
/*
 3、连接数据库(如果端口号是默认的 27017,可以省略不写)
   3.1 数据库连接成功事件 => mongoose.connection.once("open", function () {});
 */
mongoose.connect("mongodb://127.0.0.1/my_test", {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.connection.once("open", function () {
    console.log("连接成功")
});
// 4、基本使用
// 创建 Schema 对象
var Schema = mongoose.Schema;
var stuSchema = new Schema({
    name: String,
    age: Number,
    gender: {
        type: String,
        default: "female"  // 默认值
    },
    address: String
});
// 创建 Model,集合名称为 students,如果写的是单数 student,集合中会自动变成复数
var stuModel = mongoose.model("student", stuSchema);
// 插入
stuModel.create([
        {
            name: "孙悟空",
            age: 18,
            gender: "male",
            address: "花果山"
        },
        {
            name: "白骨精",
            age: 16,
            // gender: "male",    // 有默认值不写会将默认值插入
            address: "白骨洞"
        }
    ],
    function (err) {
        if (!err) {
            console.log("插入成功")
        }
    });
// 查询,总会返回一个数组,findOne 返回一个对象
stuModel.find({}, function (err, docs) {
    if (!err){
        console.log(docs)
    }
});
stuModel.find({name: "孙悟空"}, function (err, docs) {
    if (!err){
        console.log(docs[0].name)
    }
});
// 第二个参数为投影
stuModel.find({}, {name: 1, _id: 0}, function (err, docs) {
    if (!err){
        console.log(docs)
    }
});
// 不需要投影的字段在字段面前添加负号
stuModel.find({}, "name age -_id", function (err, docs) {
    if (!err){
        console.log(docs)
    }
});
// 第三个参数为限制条件
stuModel.find({}, "name age -_id", {skip: 3, limit: 1}, function (err, docs) {
    if (!err) {
        console.log(docs)
    }
});
// 根据 id 查询
stuModel.findById("5dd4b0f808f9731d481351b0", function (err, docs) {
    if (!err) {
        console.log(docs)
    }
});
// 修改
// 更新,ide 提示最好使用 updateMany 更新多个值,而不是 update 设置 multi 属性,即最好使用 updateOne 和 UpdateMany,删除也是如此
stuModel.updateMany({age: 16}, {$set: {age:18}},function (err) {
    if (!err){
        console.log("修改成功")
    }
});
// 删除
stuModel.deleteOne({name: "唐僧"}, function (err) {
   if (!err){
       console.log("删除成功")
   }
});
// 统计文档数量
// collection.count is deprecated, and will be removed in a future version. Use Collection.countDocuments or Collection.estimatedDocumentCount instead
stuModel.countDocuments(function (err, count) {
    if (!err){
        console.log(count)
    }
});
/*
 5、断开数据库连接
   5.1 数据库断开事件 => mongoose.connection.once("close", function () {});
 */
// MongoDB 数据库无事务控制一般情况下,只需要连接一次,除非项目停止或者服务器关闭,否则连接一般不会断开,即这个函数一般不会调用
mongoose.disconnect();
mongoose.connection.once("close", function () {
    console.log("连接库断开")
});

Document 的使用

// Document 是 Model 的 实例,通过 Model 查询到的结果都是 Document
var stu = new stuModel({
    name: "猪八戒",
    age: 20,
    gender: "male",
    address: "高老庄"
});
// 保存
stu.save(function (err) {
   if (!err){
       console.log("保存成功")
   }
});
// 修改
stuModel.findOne({}, function (err, doc) {
    // 返回查询到的对象
    if (!err) {
        // 直接修改就修改对象本身
        doc.updateOne({$set: {age: 28}}, function (err) {
            if (!err) {
                console.log("修改成功")
            }
        });
        // 也可以这样修改
        doc.age = 20;
        doc.save();
    }
});
// 删除
stuModel.findOne({}, function (err, doc) {
    // 返回查询到的对象
    if (!err) {
        doc.remove(function (err) {
            if (!err){
                console.log("删除成功")
            }
        })
    }
});

练习

// 1.进入 my_test 数据库
use my_test;

// 2.向数据库的 user 集合中插入一个文档
db.user.insert({
    username: "zhubajie"
});

// 3.查询 user 集合中的文档
db.user.find();

// 4.向数据库的 user 集合中插入一个文档        
db.user.insert({
    username: "sunwukong"
});

// 5.查询数据库 user 集合中的文档
db.user.find();

// 6.统计数据库 user 集合中的文档数量
db.user.find().count();

// 7.查询数据库 user 集合中 username 为 sunwukong 的文档
db.user.find({
    username: "sunwukong"
});

// 8.向数据库 user 集合中的 username 为 sunwukong 的文档,添加一个 address属性,属性值为 huaguoshan
db.user.update(
    {
        username: "sunwukong"
    }, 
    {
        $set: {
            address: "huaguoshan"
        }
    }
);

// 9.使用 {username: "tangseng"} 替换 username 为 zhubajie 的文档
db.user.replaceOne({username: "zhubajie"}, {username: "tangsheng"});

// 10.删除 username 为 sunwukong 的文档的 address 属性
db.user.update(
    {
        username: "sunwukong"
    }, 
    {
        $unset: {
            address: "huaguoshan"
        }
    }
);

// 11.向 username 为 sunwukong 的文档中,添加一个 hobby: {cities: ["beijing", "shanghai", "shenzhen"], movies:["sanguo", "hero"]}
db.user.update(
    {
        username: "sunwukong"
    }, 
    {
        $set: {
            hobby: { 
                cities: ["beijing", "shanghai", "shenzhen"], 
                movies: ["sanguo", "hero"]
            }
        }
    }
);

// 12.向 username 为 tangseng 的文档中,添加一个 hobby: {movies: ["A Chinese Odyssey", "King of comedy"]}
db.user.update(
    {
        username: "tangsheng"
    }, 
    {
        $set: {
            hobby: {movies: ["A Chinese Odyssey", "King of comedy"]}
        }
    }
);

// 13.查询喜欢电影 hero 的文档
db.user.find({
    "hobby.movies": "hero"
});

// 14.向 tangseng 中添加一个新的电影 Interstellar
// $push 用于向集合中添加新文档
// $addToSet 也用于向集合中添加新文档,但是当数组中已经存在该元素时,则不会添加
db.user.update(
    {
        username: "tangsheng"
    }, 
    {
        $addToSet: {
            "hobby.movies": "Interstellar"
        }
    }
);

// 15.删除喜欢 beijing 的用户
db.user.remove({"hobby.cities": "beijing"});

// 16.删除 user 集合
db.user.drop();

// 17.向 numbers 中插入 20000 条数据
// 5.89 秒
for (var i = 0; i < 20000; i++) {
    db.numbers.insert({num: i})
}
// 0.546 秒
var arr=[];
for (var i = 0; i < 20000; i++) {
    arr.push({num: i})
}
db.numbers.insert(arr);

// 18.查询 numbers 中 num 为 500 的文档
db.numbers.find({num:500});

// 19.查询 numbers 中 num 大于 5000 的文档
db.numbers.find({num:{$gt:500}});

// 20.查询 numbers 中 num 小于 30 的文档
db.numbers.find({num:{$lt:30}});

// 21.查询 numbers 中 num 大于 40 小于 50 的文档
db.numbers.find({num:{$gt:40, $lt:50}});

// 22.查询 numbers 中 num 大于 19996 的文档
db.numbers.find({num:{$gt:19996}});

// 23.查看 numbers 集合中的前 10 条数据
db.numbers.find().limit(10);

// 24.查看 numbers 集合中的第 11 条到 20 条数据
db.numbers.find().limit(10).skip(10);

// 25.查看 numbers 集合中的第 21 条到 30 条数据
db.numbers.find().limit(10).skip(20);

// 26.查询工资小于 2000 的员工
db.emp.find({sal:{$lte:2000}});

// 27.查询工资在 1000-2000 之间的员工
db.emp.find({sal:{$gt:1000, $lt:2000}});

// 28.查询工资小于 1000 或大于 2500 的员工
db.emp.find({$or:[{sal:{$lt:1000}}, {sal:{$gt:2500}}]});

// 29.查询财务部的所有员工
var deptno = db.dept.findOne({dname: "财务部"}).deptno;  // find 返回数组,findOne 返回对象
db.emp.find({depno: deptno});

db.emp.find({depno: db.dept.findOne({dname: "财务部"}).deptno});

// 30.查询销售部的所有员工
db.emp.find({depno: db.dept.findOne({dname: "销售部"}).deptno});

// 31.查询所有 mgr 为 7698 的所有员工
db.emp.find({mgr: 7698});

// 32.为所有薪资低于 1000 的员工增加工资 400 元
db.emp.updateMany({sal: {$lte:1000}},{$inc:{sal:400}});
db.emp.update(
    {
        sal: {$lte:1000}
    },
    {
        $inc:{sal:400}
    },
  {
    multi: true
  }
);

新评论