MongoDB最简教学

1,282 阅读3分钟

MongoDB 是一个基于 分布式文件存储 的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB的本地复制和自动故障转移功能使您的应用程序具有企业级的可靠性和操作灵活性。

关系型和非关系型数据库

关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,简单来说就是存在一对一、 一对多、多对一、 多对多这些关系的数据库。
SQL 语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作。主流的关系型数据库: Oracle、MySQL

非关系型数据库 NoSQL ( Not Only SQL ),
意思是“不仅仅是 SQL”, 主流的 NoSQL 数据库有: Redis、MongoBD

  • 查询速度

nosql数据库优于关系型数据库。nosql数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查询速度远不及nosql数据库。

  • 安全

关系型数据库优于nosql数据库。因为关系型数据库存储在磁盘中,不会说突然断电数据就没有了。但其中redis可以同步数据到磁盘中,现在很多非关系型数据库都开始支持转存到磁盘中。

  • 术语对比

image.png image.png

历史

2007年10月,MongoDB由10gen团队所发展。2009年2月首度推出。

下载安装

点击下载MongoDB 注意不用自己去下载MongoDB Compass 安装完MongoDB会自动提示你要不要安装Compass (UI界面操作,如果没下只能用shell操作) 。这里还是附上Compass下载链接

安装时一路点击next即可

连接

在D盘创建一个项目文件 Data, 在里面创建数据库文件夹 db, 再执行下面命令

mongod --dbpath D:\data\db

正常情况会提示连接成功, 默认27017端口, 也可以浏览器验证 localhost:27017/

image.png

但是启动了mongodb服务后发现这个窗口一直连着, 无法输入了, 这时候得重新开个shell窗口操作, 但是一般不用shell操作数据库。

演示的时候直接输入mongo 回车即可进入mongodb shell

image.png

常用命令

use school  //有这个数据库时会切换到这个数据库, 没有这个数据库时会创建一个

show dbs //展示所有数据库名称

db.dropDatabase()  //删除当前数据库

db.createCollection('grade_1')  //创建集合

show collections 或者 show tables  // 展示当前数据库所有集合

db.grade_1.drop()  //删除集合

往集合添加文档

db.myCol.insertOne({name: '马保国', like: "闪电五连鞭"})   // myCol集合插入一条文档

//插入多条文档
db.myCol.insertMany([
    {name: "杨过", like: "大宝剑"},
    {name: "梅超风", age: 18 }
])

db.insert([])  //支持插入插入单个或多个

删除

db.myCol.deleteOne({name: "杨过"}) //删除一个

db.myCol.deleteMany({name: "杨过"}) //删除所有叫杨过的文档   

更新

更新文档 - 新增了字段age, 更改了字段like

db.myCol.UpdateOne({name: "马保国"}, {
    $set: {age: 70},
    $like: '接化发'
})
//$set:已存在的字段执行更新, 不存在的字段就新建字段

//更新多个 - 把小于30岁的人全部打上“年轻人”标签

db.myCol.updateMany(
    {age: {$lt: 30}},
    {
        $set: {tag: "年轻人"},
        $currentDate: { lastModified: true }   //更新操作时间
    }
)

直接替换- 杨过换成了包租公,
注意文档_id字段是不可替换的,如果新的文档有这个字段必须跟旧的一致(最好别传这个字段)

db.myCol.replaceOne(
    {name: "杨过"},
    {name: "包租公", like: "阿珍"}
)

查询

db.myCol.find({name: "包租公"})

使用操作符查询 (查看目前支持的操作符

db.myCol.find({
    name: {
        $in: ["马保国", "包租公"]  //查询名称 =马保国 或者 =包租公  的全部文档
    }
})

//筛选出name为包租公,并且年龄小于50、喜欢阿珍 的文档
db.myCol.find({
    name: "包租公",
    $and: [
        {age: {$gt: 50} },
        {like: '阿珍'}
    ]
})    

返回指定字段文档

db.myCol.inserOne({type: 1,  phone: "181xxx",  color: "red",  parent: "xxxx"})
db.myCol.find(
    {type: 1},
    {phone: 1, color: 1}   //只返回phone字段和color字段
)

db.myCol.find(
    {type: 1},
    {parent: 0, _id: 0}     //返回结果不要parent字段和_id字段
)

Sort 、 Limit 、 Skip、 Count

按年龄排序

db.myCol.find().sort({ age: 1})  //升序
db.myCol.find().sort({ age: -1})  //降序

skip

db.myCol.find().skip(10); //跳过前10条记录

limit

db.myCol.find().limit(10); //只返回前10条

分页实现:

function findStudentForPage(params) {
    const { pageNo, pageSize } = params
    db.Students.find().limit(pageSize).skip((pageNo-1) * papageSize) 
}

count:

db.Students.find().count()    //返回数量统计, 常见于分页数据返回总条数或者总页码

image.png

$type

指定获取某个字段类型

db.Students.find({name: {$type: 'string'}}) //只返回name是字符串的数据        

聚合

image.png

上面这个学生表有班级和分数、等级

 db.Students.aggregate([
     { $match: {class: 1} }  //匹配 1班的同学
 ])

image.png

获取一班学生总分数

db.Students.aggregate([
    { $match: {class: 1} },
    { $group: {_id: "$_class", total: {$sum: "$score"}} }
])

image.png

获取每个班总分数

db.Students.aggregate([
    { $group: {_id: "$class", total: {$sum: "$score"}} }
])

image.png

求每个班平均分

db.Students.aggregate([
    { $group: {_id: "$class", avg: {$avg: "$score"}} }
])

image.png

Node中连接mongodb

npm i mongodb
const { MongoClient } = require('mongodb');
// or as an es module:
// import { MongoClient } from 'mongodb'

const url = 'mongodb://localhost:27017';
const client = new MongoClient(url);

// Database Name
const dbName = 'zsq';

async function main() {
    await client.connect();
    console.log('连接成功');
    const db = client.db(dbName);
    const collection = db.collection('Students');

    //do something
    await getAllStudents(collection)
}

async function getAllStudents(Col) {
    const students = await Col.find().toArray()
    console.log(students)
}

main()
    .then(console.log)
    .catch(console.error)
    .finally(() => client.close());

image.png

实际项目中上面代码还要拆分的, 不可能把所有业务写到main 里面, 把db暴露出去就可以了, 还有一个注意点, Collection.find() 后面加了toArray()

表关联 - lookup

虽然MongoDB不是关系型数据库, 但是它也可以关联表操作数据

{ 
$lookup: { 
    from: 'products',  //关联的表名称
    localField: 'product_id', // 当前表的关联字段
    foreignField: '_id', // 关联的表里对应字段 
    as: 'orderdetails' // 新生成字段(类型array)
  } 
}

下面演示个示例, 首先建了两个集合

image.png

async function main() {
    await client.connect();
    const db = client.db(dbName);
    const Orders = db.collection('orders');

    const data = await Orders.aggregate([
        {
            $lookup: {
                from: "products",
                localField: "product_id",
                foreignField: "_id",
                as: "productDetails"
            }
        }
    ]).toArray()

    console.log(data)
}

image.png

当然关联之后返回的数据我们也是可选的 - $project $match

db.collection('orders').aggregate([
    {
        $lookup: {
            from: "products",
            localField: "product_id",
            foreignField: "_id",
            as: "productDetails"
        },
    },
    {
         $match: {
             status: "已发货"
         }
    },
    {
        $project: {
            productDetails: 1  
        }
    }
])

本片结束, 古德拜

参考文档

docs.mongoing.com/
www.runoob.com/mongodb/mon…