前言
如果一个网站需要存储大量的信息,那么就需要用到数据库。数据库的CRUD(增删改查)操作是后端服务器的一项重要的操作。在这篇文章中,我们就来聊一聊数据库。数据库就是一个存放数据的仓库,这个仓库按照一定的数据结构来组织存储数据。按照早期的数据库理论,比较流行的数据库模型有三种,分别是层次式数据库、网络式数据库和关系型数据库(前两者已经基本消失)。当今的互联网中,最常见的数据库模型有两种关系型数据库(RDBMS,Relational Database Management System)和非关系型数据库(noSQL)。关系型数据库,比较著名的有Oracle、MySQL;非关系型数据库,即NoSQL,其含义不是"no sql",而是"not only SQL",不仅仅是SQL。SQL的全称是"Structured Query Language(结构化查询语言)",是专门为数据库而建立的造作命令集,是一种功能齐全的数据库语言。类似JavaScript的声明式编程,在使用时只需要考虑"做什么",而不需要考虑"怎么做"。常见的非关系型数据库有Redis,还有我们今天的主角MongoDB。
mongoDB
mongoDB基本概念
MongoDB是面向文档的数据库,其中有三个重要的概念:数据库(database)、集合(collection)、文档(document).
- 数据库(database):和SQL中的数据库相对应,表示数据库,可以理解为所有的数据都存在这个空间中
- 集合(collection):和SQL中的tabel相对应,表示数据表/集合,可以理解为存储的某一类数据
- 文档(document):和SQL中的row相对应,表示数据记录行/文档,可以理解为存储的某一条数据
显然,这三个概念之间存在一种包含关系,数据库中包含很多个集合,集合中包含很多文档。从数学集合的观点来看,数据库是集合的集合,集合是文档的集合。下图是三者关系的直观表示。
除此之外,MongoDB中还有三个关键概念:字段(field)、索引(index)、主键(primaryy key). - 字段(field):如果说document代表的是SQL语言中的row的话,那么字段这个概念代表的就是SQL中的column。也可以理解为键值对(key-value)中的“键”.
- 索引(index):这个概念看名称就知道了,无需多言
- 主键(primary key):MongoDB数据库中的数据的唯一标识,默认主键为
_id字段 到此,mongoDB中的基本概念就介绍完了。接下来,我们看一条真实存储在mongoDB数据库中的数据: - 在数据库中的样子:
可以看到,该条数据,或者可以说这个文档,有七个字段,主键是
_id。当数据通过被查询到之后就会以如下的json的格式返回
{
"_id" : ObjectId("60d571d606d8634c18cf2338"),
"agreeArticle" : [],
"username" : "ggg",
"password" : "202cb962ac59075b964b07152d234b70",
"type" : "normal",
"agreeCount" : 0,
"__v" : 0
}
使用
在javascript中关于mongoDB的使用,主要是通过中间库mongoose来实现的。因此,很多操作都只需要调用mongoose即可,这些操作将在下一部分进行介绍。在这里,主要介绍mongoDB中文档的CRUD(增删改查)操作。在执行文档的CRUD操作之前,应该现有现有数据库和集合这两个要素。而在所有的操作之前,应该先安装和启动mongoDB,并且建立数据库的连接
安装和启动mongoDB
- 安装和启动mongoDB,请戳下面的链接:www.runoob.com/mongodb/mon…
- mongoDB启动数据库服务,请戳下面的链接:www.runoob.com/mongodb/mon…
数据库
关于数据库的操作的关键命令如下:
- 创建数据库:
use DATABASE_NAME - 显示数据库列表:
show dbs - 显示当前数据库:
db - 删除数据库:
db.dropDatabase()
注意:删除数据库的操作需要谨慎使用!!!
集合
关于集合操作的几条关键命令如下:
- 创建集合:
db.createCollection("COLLECTION_NAME") - 显示当前数据库中的集合:
show collections - 删除集合:
db.COLLECTION_NAME.drop()
文档
- 增(create):
在mongoDB中,我们需要将document插入到collection中。每一个document的数据结构和JSON基本一样。但是这种数据结构在mongoDB中不叫作JSON,而是叫做BSON,是Binary JSON的简称。接下来,我们来关注在collection中插入document的语法。db.COLLECTION_NAME.insert(document):若插入的数据主键已经存在,则会抛出org.springframework.dao.DuplicateKeyException异常,提示主键重复,不保存当前数据db.COLLECTION_NAME.save(document):如果_id主键存在则更新数据,如果不存在就插入数据。该方法在新版本中已废弃,可以用db.collection.insertOne()或db.collection.replaceOne()来代替。db.COLLECTION_NAME.insertOne(<document>,{writeConcern:<document>}): 3.2版本之后新增的插入方法。其中,<document>表示要写入的文档;writeConcern表示写入策略,默认为 1,即要求写入操作,0 是不要求。db.COLLECTION_NAME.insertMany([<document 1>, <document 2>, ... ],{writeConcern: <document>, orderd: <boolean>}):3.2版本之后新增的插入方法。其中,<document>和writeConcern的含义与之前相同,ordered表示是否按顺序写入,默认为true,按顺序写入。
writeConcern字段的含义,相关文档是这样表述的: Write concern describes the level of acknowledgment requested from MongoDB for write operations to a standalone mongod or to replica sets or to sharded clusters. In sharded clusters, mongos instances will pass the write concern on to the shards. write Concern 包含下列字段:
{
w: <value>,
j: <boolean>,
wtimeout: <number>
}
详情请参考相关文档,相关文档链接如下:docs.mongodb.com/manual/refe…
- 删(delete)
删除文档的语法如下:db.collection.remove( <query>, { justOne: <boolean>, writeConcern: <document> } )<query>:可选参数,表示删除文档的条件justOne:可选参数,如果设为true 或 1,则只删除一个文档;如果不设置该参数,或者使用默认值false,则删除所有匹配条件的文档。writeConcern:可选参数,表示抛出异常的级别。
- 改(update)
更新文档的语法如下:
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )query:update的查询条件update:update的对象和一些更新的操作符upsert:可选参数,如果不存在update记录,是否插入objNew,true为插入,false为不插入,默认值。multi:可选参数,默认为false,只更新找到的第一条记录;如果设置为true,则更新符合条件的全部数据writeConcern:可选参数,表示抛出异常的级别
- 查(retrieve)
mongoDB的查询操作,可以参考下面的文章,此处不再赘述: juejin.cn/post/684490…
mongoose
mongoose是一个使用nodeJS来操作mongoDB数据库的开源库。mongoose里面封装了连接数据库、创建collection和document CRUD的操作。
安装mongoose
在自己的项目中运行:npm install mongoose --save
连接数据库
废话不多说,直接贴代码:
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test',
{useNewUrlParser: true, useUnifiedTopology: true})
const db = mongoose.connection;
db.on('open', function() {
// 数据库连接成功的回调函数
});
Schema 和 Model
在mongoose中,Schema是起点,它与mongoDB中的collection相对应,并且定义了collection中每一个document的数据结构。下面是一个Schema的使用实例:
import mongoose from 'mongoose';
const { Schema } = mongoose;
const blogSchema = new Schema({
title: String, // String is shorthand for {type: String}
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});
在这段代码中,规定了blogSchema的字段,以及每一个字段的数据类型。在mongoDB中,collection是document的集合,而Schema对应的是mongoDB的collection。那么,另一个与document对应的概念就是model。一个model的实例就是一个document。因此,mongoDB数据库中数据的增删改查在mongoose中都是利用Model来进行的。使用model的第一步是调用mongoose.model方法:
const Blog = mongoose.model('Blog',blogSchema)
容易看到,这个方法需要传入两个参数,一个是集合的名称,另一个是schema对象。在调用了这个方法之后,可以进行数据的增删改查操作了:
- 增
向数据库中添加数据的操作,首先需要实例化一个model对象,这个很容易理解,要向数据库添加数据,首先需要有数据才能够添加。然后,调用model.save()方法即可。例子如下:new Blog({ title: 'xxx', // String is shorthand for {type: String} author: 'xxx', body: 'xxx', comments: [], date: Date.now, hidden: true, meta: { votes: 0, favs: 0 } }).save((err) => { // 这是一个回调函数,处理该条数据保存之后的操作 })model.save()返回的是一个promise对象。因此,回调函数也可以携程链式调用的形式。 - 删
删除操作有两个方法可以调用:deleteOne()和deleteMany()。使用这两个方法,需要传入需要删除的数据的条件还可以采用Tank.deleteOne({ size: 'large' }, function (err) { if (err) return handleError(err); // deleted at most one tank document });Model.findOneAndDelete(),使用方法和前面的一样 - 改
更新数据的操作可以采用的方法有:Model.findOneAndUpdate()Model.update()Model.updateMany()Model.updateOne()需要的参数如下:- conditions:需要更新的数据的筛选条件
- update:更新之后大数据
- options:可选参数,该方法的一些配置选项
- callback:执行完更新操作之后的回调函数,这里需要注意一个问题:回调函数有两个参数err和data,这里的data表示的是原始数据,而不是更新完之后的数据。
- 查
查询数据库中数据的方法有:Model.find()Model.findOne()Model.findMany()需要的参数仅仅是更新操作除掉第二个参数,其余都相同。
Query
关于query对象的特性,有很多。但是,似乎在简单的应用里都不怎么能够用得到。但是,可以拿它当promise对象来用。当然,用的时候可以这么用,还是要记住他俩是有区别的。
写在后面的话
这篇文章是我第一次使用mongoDB和mongoose做项目之后总结的一些内容,因此原则是够用就好。显然,它们还有很多很多重要的特性。如果需要用到,必须要参考官方的文档了。
官方文档存档: