目录
创建数据库(在首次插入数据时会自动创建,也可通过 use 命令切换到未创建的数据库名来隐式创建)
简介
MongoDB 是一款基于分布式文件存储的开源文档型数据库管理系统,采用C++语言编写,专门为了应对大规模数据存储和高并发访问而设计。它属于NoSQL(非关系型数据库)类别,与传统的关系型数据库管理系统(如MySQL、PostgreSQL)相比,MongoDB 不依赖于预定义的列模式(schema),而是采用灵活的文档数据模型。在MongoDB中,数据以JSON-like(即BSON,Binary JSON)格式存储,每个文档可以有动态的键值对集合,允许存储嵌套的数据结构。这意味着MongoDB能够轻松处理结构化、半结构化乃至非结构化的数据。
特点
分布式存储:MongoDB支持水平扩展,通过分片(sharding)可以在多台机器上分布数据,提高系统的整体性能和容量。
高可用性和容错性:通过复制集(replica sets)确保数据冗余和自动故障转移。
灵活的数据模型:无需预先定义数据结构,能够随需求变化自由调整文档结构。
强大的查询能力:支持丰富的查询表达式,包括地理空间索引、文本搜索等功能。
自动索引:可以为文档中的字段创建索引,加速查询性能。
快速响应:特别适合需要低延迟读写操作的应用场景,例如实时分析、内容管理系统、物联网(IoT)应用等。
核心概念
文档 (Document)
文档是MongoDB中数据的基本单元,它是JSON-like格式(BSON,在传输过程中采用二进制编码)的一个数据结构,包含多个键值对。文档相当于关系型数据库中的行记录,但比之更为灵活,因为其内部结构可以嵌套且不需要预定义模式。
集合 (Collection)
集合是MongoDB中一组文档的集合,没有特定的顺序。集合中的文档可以有不同的字段,也就是说集合中的文档结构并不严格要求一致。集合在功能上类似于关系型数据库中的表。
数据库 (Database)
在MongoDB中,可以创建多个数据库来组织和隔离数据。每个数据库都包含一系列的集合以及相关的用户权限设置。数据文件会根据所选择的数据库进行物理上的隔离。
下载安装
下载地址:https://www.mongodb.com/try/download/community
选择zip类型,将压缩包解压到指定目录,并且在对应盘符下创建data/db目录,以mongodb中的bin目录作为工作目录,启动命令行,运行命令mongod,出现如下信息,服务就算启动成功。
mongo.exe是 MongoDB 提供的命令行工具,它是 MongoDB 客户端程序,主要用于与 MongoDB 服务器进行交互。在 Windows 环境下,安装了 MongoDB 后,通常可以在 MongoDB 的 bin 目录下找到 mongo.exe
文件。启动命令行,运行mongo命令。
MongoDB数据库与集合命令
数据库相关命令
创建数据库(在首次插入数据时会自动创建,也可通过 use 命令切换到未创建的数据库名来隐式创建)
use myDatabase
列出所有数据库
show dbs
删除数据库(需确认当前已连接至其他数据库)
db.dropDatabase()
集合相关命令
创建集合
db.createCollection("myCollection")
显示当前数据库中的所有集合
show collections
插入一条记录到集合(若集合不存在则自动创建)
db.myCollection.insertOne({ name: "test", count: 10 })
删除集合
db.collection_name.drop()
文档命令
插入文档
drop.集合名.insert("文档对象")
查询文档
drop.集合名.find("查询条件")
删除文档
drop.集合名.remove("查询条件")
更新文档
drop.集合名.update("查询条件","新的文档")
drop.集合名.update({name:"李四"},{$set:{age:99}})
Mongoose
官网:https://www.mongoosejs.net/
mongoose 是一个基于Node.js的开源对象数据模型(ODM)库,用于简化与MongoDB数据库的交互。它可以让我们以面向对象的方式定义数据模型(Schema),并提供了丰富的API来进行数据库的CRUD(创建、读取、更新和删除)操作以及其他高级功能。
Mongoose连接数据库
通过npm i mongoose安装
// 导入 mongoose
const mongoose = require('mongoose');
// 连接 mongodb 服务 数据库名称,如果没有就创建
mongoose.connect('mongodb://127.0.0.1:27017/mydb');
// 设置回调
// 设置连接成功的回调 once 一次 事件回调函数只执行一次
mongoose.connection.once('open', () => {
console.log('连接成功');
});
// 设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('连接失败');
});
// 设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
字段类型
String | 字符串 |
Number | 数字 |
Boolean | 布尔值 |
Array | 数组,也可以使用[]标识 |
Date | 日期 |
Buffer | Buffer对象 |
Mixed | 任意类型,需要使用mongoose.Schema.Types.Mixed指定 |
ObjectId | 对象ID,需要使用mongoose.Schema.Types.ObjectId指定 |
Decimal128 | 高精度数字,需要使用mongoose.Schema.Types.Deimal28指定 |
// 属性名要对应
let phSchema = new mongoose.Schema({
name: String,
price: Number,
xn: Boolean,
pp: Array,
time: Date,
test: mongoose.Schema.Types.Mixed
})
phModel.create({
name: '手机',
price: 9.9,
xn: true,
pp: ['华为','苹果','小米'],
time: new Date(),
test: new Date()
})
Mongoose字段验证
必填项
title: {
type: String,
required:true //必填
}
默认值
title: {
type: String,
default: '匿名'
}
枚举值
gender: {
type: String,
enum: ['男','女'] // 设置的值必须是其中的
}
唯一值
name: {
type: String,
unique:true
}
示例代码
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/mydb');
mongoose.connection.once('open', () => {
let phSchema = new mongoose.Schema({
name: {
type: String,
required: true, // 类似设置非空索引
unique: true // 类似设置唯一索引
},
xp: {
type: Boolean,
default: '匿名'
},
pp: {
type: String,
// 枚举
enum: ['华为','小米','三星','苹果']
},
price: Number
});
let phModel = mongoose.model('phs', phSchema);
// 增
phModel.create({
name: '手机',
xp:true,
pp: '三星',
price: 9.9,
}, (err, data) => {
if(err) {
console.log(err);
return;
}
console.log(data);
mongoose.disconnect();
});
});
mongoose.connection.on('error', () => {
console.log('连接失败');
});
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
插入文档
const mongoose = require('mongoose');
// 连接 mongodb 服务 数据库名称,如果没有就创建
mongoose.connect('mongodb://127.0.0.1:27017/mydb');
mongoose.connection.once('open', () => {
// 创建文档的结构对象
// 设置集合中文档的属性以及属性值的类型
let SPSchema = new mongoose.Schema({
name: String,
price: Number
});
// 创建模型对象 对文档操作的封装对象
let SPModel = mongoose.model('sps', SPSchema);
// 新增
SPModel.create({
name: '手表',
price: 9.9
}, (err, data) => {
if(err) {
console.log(err);
return;
}
// 输出插入后的文档对象
console.log(data);
// 关闭数据库连接
mongoose.disconnect();
});
});
// 设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
命令行输入mongo,查询后得到:
删除文档
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/mymgdb');
mongoose.connection.once('open', () => {
let FilmSchema = new mongoose.Schema({
name: String,
ticket:Number,
country: String
});
let FilmModel = mongoose.model('films', FilmSchema);
// 删除一条
// 删除多条deleteMany
// 可以通过name等等条件删除,以及 _id:'id'
FilmModel.deleteOne({name:'三体'}, (err, data) => {
if(err) {
console.log(err);
return;
}
console.log(data);
mongoose.disconnect();
});
});
mongoose.connection.on('error', () => {
console.log('连接失败');
});
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
更新文档
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/mymgdb');
mongoose.connection.once('open', () => {
let FilmSchema = new mongoose.Schema({
name: String,
ticket:Number,
country: String
});
let FilmModel = mongoose.model('films', FilmSchema);
// 更新一条
// 更新多条updateMany
FilmModel.updateOne({name:'流浪地球'},{name:'流浪地球2.0'}, (err, data) => {
if(err) {
console.log(err);
return;
}
console.log(data);
mongoose.disconnect();
});
});
mongoose.connection.on('error', () => {
console.log('连接失败');
});
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
读取文档
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/mymgdb');
mongoose.connection.once('open', () => {
let FilmSchema = new mongoose.Schema({
name: String,
ticket:Number,
country: String
});
let FilmModel = mongoose.model('films', FilmSchema);
// 读取一条
// 读取多条find
FilmModel.findOne({name:'新桥恋人'}, (err, data) => {
if(err) {
console.log(err);
return;
}
console.log(data);
mongoose.disconnect();
});
// 结果
/**
* // 根据ID读取
* FilmModel.findById('id号', (err, data) => {
if(err) {
console.log(err);
return;
}
console.log(data);
mongoose.disconnect();
});
*/
});
mongoose.connection.on('error', () => {
console.log('连接失败');
});
mongoose.connection.on('close', () => {
console.log('连接关闭');
});
/**
*{
* _id: new ObjectId("65eab01fb75028e7cff79f00"),
* name: '新桥恋人',
* ticket: 999,
* country: '法国',
* __v: 0
*}
*/
Mongoose条件控制
/**
* 运算符
* > $gt
* < $lt
* >= $gte
* <= $lte
* !== $ne
*
* 逻辑运算
* $or 逻辑或
* $and 逻辑与
*
* 正则表达式
* / /
* new RegExp
*/
// 中国或者美国电影
FilmModel.find({$or: [{country: '中国'}, {country: '美国'}]}, (err, data) => {
if (err) {
console.log('读取失败');
return;
}
console.log(data);
})
// 价格大于 30 且小于 70
FilmModel.find({$and: [{ticket: {$gt: 30}}, {ticket: {$lt: 70}}]}, (err, data) => {
if (err) {
console.log('读取失败');
return;
}
console.log(data);
})
// 正则表达式, 搜索电影名称中带有 `恋人` 的电影
FilmModel.find({name: /恋人/}, (err, data) => {
if (err) {
console.log('读取失败');
return;
}
console.log(data);
})
FilmModel.find({name: new RegExp('恋人')}, (err, data) => {
if (err) {
console.log('读取失败');
return;
}
console.log(data);
})
个性化读取
// 字段筛选 0:不要 1:要
/**
* FilmModel.find().select({name: 1, ticket: 1, country: 0}).exec((err, data) => {
if(err) {
console.log('查询失败');
return;
}
console.log(data);
})
*/
// 数据排序 -1:按门票降序 1:升序
/**
* FilmModel.find().select({name: 1, ticket: 1, country: 0}).sort({ticket: -1}).exec((err, data) => {
if(err) {
console.log('查询失败');
return;
}
console.log(data);
})
*/
// 数据的截取 skip:跳过 limit:限定
/**
* FilmModel.find()
.select({name: 1,ticket: 1})
.sort({ticket: -1})
.skip(2)
.limit(2)
.exec((err, data) => {
if(err) {
console.log('查询失败');
return;
}
console.log(data);
})
*/
Mongoose代码模块化
首先看模块化后的目录结构如下:
config
config/config.js模块导出的对象定义了与MongoDB数据库连接相关的三个配置属性:
DBHOST: 这个字段指定了MongoDB数据库服务器的主机地址,默认值 '127.0.0.1' 表示数据库运行在本地计算机上。
DBPORT: 定义了MongoDB数据库服务监听的端口号,默认MongoDB使用的端口是 27017。
DBNAME: 指定要连接的数据库名称,在这个例子中是要连接到名为 'mymgdb' 的数据库。
module.exports = {
DBHOST:'127.0.0.1',
DBPORT:'27017',
DBNAME:'mymgdb'
}
db
db/db.js模块是一个用于管理MongoDB数据库连接的Node.js模块,它以函数的形式对外提供接口,能够更好地处理数据库连接的成功、失败和关闭状态,并允许用户自定义相应的回调函数。模块的主要内容及作用如下:
函数接受两个参数:success 和 error,它们分别代表数据库连接成功和失败时的回调函数。为了确保错误处理的完整性,模块首先检查 error 是否为函数类型,如果不是,则为 error 设置一个默认的处理函数,即在控制台输出“连接失败”。
从'/config/config' 加载配置信息,获取数据库主机地址(DBHOST)、端口号(DBPORT)以及数据库名称(DBNAME),基于这些信息构造出一个指向MongoDB数据库的连接字符串。
使用构造好的连接字符串调用 mongoose.connect() 方法尝试建立到数据库的连接。当数据库成功连接时,mongoose.connection 上的 'open' 事件被触发,并调用 success 回调函数,通知外部应用数据库连接已经成功建立。
如果在尝试连接数据库过程中发生错误,mongoose.connection 上的 'error' 事件将被触发,并调用 error 回调函数,允许外部应用根据实际情况进行错误处理。
此外,模块还监听了 'close' 事件,当数据库连接关闭时,会在控制台输出“关闭”,提示当前数据库连接状态已断开。
// success:数据库连接成功的回调
//error:数据库连接失败的回调
module.exports = function (success, error) {
//判断error,为其设置默认值
if(typeof error !== 'function'){
error = () => {
console.log("连接失败...")
}
}
//导入mongoose
const mongoose = require("mongoose")
//导入config配置文件.
const {DBHOST,DBPORT,DBNAME} = require('../config/config')
//连接数据库
mongoose.connect(`mongodb://${DBHOST}:${DBPORT}/${DBNAME}`)
//设置连接成功
mongoose.connection.once('open', async () => {
success()
})
//设置连接失败
mongoose.connection.on('error', async() => {
error()
})
//设置连接关闭
mongoose.connection.on('close', async() => {
console.log('关闭')
})
}
models
models/FilmModel.js这个模块主要用于定义并导出一个基于mongoose的MongoDB数据模型。
//导入mongoose
const mongoose = require('mongoose')
//创建文档的结构对象
//设置集合中文档的属性以及属性值的类型
let FilmSchema = mongoose.Schema({
name: String,
ticket:Number,
country:String
})
//创建模型对象---对文档操作的封装对象
let FilmModel = mongoose.model('films', FilmSchema)
//暴露模型对象
module.exports = FilmModel
code
code/test.js主要编写操作数据库的代码
//导入mongooses
const mongoose = require('mongoose')
//导入db
const db = require('../db/db')
//导入MovieModel
const FilmModel = require('../models/FilmModel')
//调用函数
db(async() => {
try{
//电影的模型对象
//增删改查等操作
const data = await FilmModel.create({
name: '新桥恋人',
ticket: '999',
country:'法国'
})
console.log("操作成功")
console.log(data)
mongoose.disconnect()
}
catch(err){
console.log(err)
}
})