我们用的是mongoDB

image-20241210010430932

mongoDB的结构

  • **MongoDB 实例(MongoDB Instance)**:一组数据库
  • **数据库(Database)**(例如 Catbook 数据库):一组集合,通常对应一个 Web 应用程序
  • **集合(Collection)**(例如 Stories 集合):一组非常相似的数据。理想情况下,希望给定集合中的所有数据具有相同的结构,即具有相同的键和类型
  • **文档(Document)**(例如单个故事的数据):一个单独的 JSON 或 JavaScript 对象。应用程序中的单个数据,类似于 SQL 中的行
  • **字段(Field)**(例如单个故事的 content 属性):我们希望记录其值的属性,JavaScript 对象中的键

image-20241210010603514

image-20241210010612838

image-20241210010619986

image-20241210010629026

image-20241210010635615

image-20241210010834000

Mongoose

NodeJS允许的MongoDB集成库

Mongoose做了什么

  • 连接到集群(cluster)
  • 创建文档
  • 与数据库交互
    • 创建、读取、更新、删除等操作

MongoDB的集群指的是由多个 MongoDB 实例组成的系统,它们共同存储和管理数据。MongoDB 集群通常由以下几个部分组成:

  1. 副本集(Replica Set):一组包含同一数据集的 MongoDB 实例,保证数据的高可用性和冗余。
  2. 分片(Sharding):用于分布式存储和处理大规模数据,将数据分割成多个部分并分配到不同的服务器上。
  3. 路由器(Mongos):一个中间层,用于将客户端的请求路由到合适的 MongoDB 实例或分片。

MongoDB 集群可以提高数据的处理能力,并保证即使部分节点出现故障,系统依然能够继续正常运行。

模式Schema

  • 模式(Schemas)定义文档的结构:

  • 定义键以及对应键的值的类型

  • 组织结构至关重要!

例子

image-20241210011636373

结构

image-20241210011500161

Documents的加工

  • MongoDB 文档的结构化方式

    • 指定文档中的字段
      在 MongoDB 中,你可以通过 schema 来定义文档中包含的字段和它们的数据类型。
  • 每个集合都应该有一个模式(Schema)
    每个集合的文档应该遵循一定的结构,定义哪些字段是必须的、字段的数据类型以及其他约束条件。这样可以确保数据的一致性和可管理性。

Mongoose Schema的类型

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array
  • ….

Read more about schema types: http://mongoosejs.com/docs/schematypes.html

Mongoose Models

模型(Models)让你能够:

  • 构建文档
  • 获取符合模型的文档
  • 发布文档
  • ……或执行任何与符合模型的文档相关的操作!

模型像对象一样,但我们也可以用它们来查询或修改数据库!

构建一个Mongoose Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Import mongoose
const mongoose = require("mongoose");
const mongoConectionSRV = :"your SRV";
const databaseName = "test";
const options = {useNewUrlParser: true, useUnifiedTopology: true, dbName: databaseName};

mongoose.connect(mongoConnectionSRV, options)
.then(() => console.log("Connected."))
.Catch((error) => console.log(error));222

//Create a mongoose.Schema
const UserScheme = new mongoose.Schema({
name: String,
age: Number,
pets: [String],
})

//Create a mongoose.model
const User = mongoose.model("User", UserSchema)

//Creating Documents
const Tim = new User({name: "Tim", age:21, pets["cloude"]});

Tim.save()
.then((student) => console.log('Added ${student.name}'));

finding Documents

1
2
3
4
5
6
7
8
9
10
11
//这个表示返回所有的Documents
User.find({})
.then((users) => console.log('Found ${users.length} users'));

//这个返回所有21岁的用户
User.find({age: 21})
.then((users) => console.log('Found ${users.length} users'));

//这个返回所有21岁,叫Tim的用户
User.find({name: "Tim", age: 21})
.then((users) => console.log('Found ${users.length} users'));

Deleting Documents

1
2
3
4
5
6
7
8
9
10
11
User.deleteOne({"name": "Tim"})
.then((err) => {
if (err) return console.log("error");
console.log("Deleted 1 user!");
})

User.deleteMany({"name": "Tim"})
.then((err) => {
if (err) return console.log("error");
console.log("Deleted all user!");
})

Mongoose Parameters

http://mongoosejs.com/docs/schematypes.html (from “All Schema Types”)

More advanced: http://mongoosejs.com/docs/validation.html

More advanced: http://mongoosejs.com/docs/guide.html

如何构建自己的Mongo DBMS?

第一次使用

  1. 进入网站,注册登录 MongoDB Cloud | MongoDB

  2. 第一次注册后进入的页面,首先我们先创建一个Clusters

image-20241210020243581

  1. Clusters连接

我们点击这个Connect(你创建的时候他会自动到这个页面)

image-20241210020651334

输入你的用户名和密码(后面连接时需要用到)

image-20241210020800273

单击Create Database User,然后下一步:

image-20241210020919900

Driver选成Node.js, 其中红框为我们需要的SRV, 复制我们的SRV,将<db_password>直接替换成刚才我们设置的密码即可。

image-20241210021007931

  1. 设置成允许任何人访问

image-20241210020556404

  1. 设置数据库

确保自己导航栏在Clusters

image-20241210022005354

进入Collections

image-20241210021251283

创建数据库

image-20241210021400558

我们在创建Clusters的时候可能勾选了创建sample数据库,所以他会生成一个没什么用的数据库,这个无所谓

我们需要注意的是,这里的Database name一定要和代码里设置的一样,不然访问不到,至于Collection name随意,我们传数据给数据库的时候会自动生成Collection

这样子就大功告成了

创建新的Clusters

如果我们之前创建过Clusters的话,可能没有快速开始的页面,我们需要自己从头开始.

1, 创建新项目

image-20241210021729514

image-20241210021805783

  1. 创建Cluster

image-20241210021840181

  1. 后面的步骤和第一次使用的一样了

实战

comment.js

1
2
3
4
5
6
7
8
9
10
11
12
const mongoose = require("mongoose");

//define a comment schema for the database
const CommentSchema = new mongoose.Schema({
creator_name: String,
parent: String, // links to the _id of a parent story (_id is an autogenerated field by Mongoose).
content: String,
});

// compile model from schema
module.exports = mongoose.model("comment", CommentSchema);

story.js

1
2
3
4
5
6
7
8
9
10
const mongoose = require("mongoose");

//define a story schema for the database
const StorySchema = new mongoose.Schema({
creator_name: String,
content: String,
});

// compile model from schema
module.exports = mongoose.model("story", StorySchema);

api.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
router.get("/stories", (req, res) => {
// empty selector means get all documents
Story.find({}).then((stories) => res.send(stories));
});

router.post("/story", (req, res) => {
const newStory = new Story({
creator_name: myName,
content: req.body.content,
});

newStory.save().then((story) => res.send(story));
});

router.get("/comment", (req, res) => {
Comment.find({ parent: req.query.parent }).then((comments) => {
res.send(comments);
});
});

router.post("/comment", (req, res) => {
const newComment = new Comment({
creator_name: myName,
parent: req.body.parent,
content: req.body.content,
});

newComment.save().then((comment) => res.send(comment));
});

server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
|--------------------------------------------------------------------------
| server.js -- The core of your server
|--------------------------------------------------------------------------
|
| This file defines how your server starts up. Think of it as the main() of your server.
| At a high level, this file does the following things:
| - Connect to the database
| - Sets up server middleware (i.e. addons that enable things like json parsing)
| - Hooks up all the backend routes specified in api.js
| - Fowards frontend routes that should be handled by the React router
| - Sets up error handling in case something goes wrong when handling a request
| - Actually starts the webserver
*/

// validator runs some basic checks to make sure you've set everything up correctly
// this is a tool provided by staff, so you don't need to worry about it
const validator = require("./validator");
validator.checkSetup();

// import libraries needed for the webserver to work!
const express = require("express"); // backend framework for our node server.
const mongoose = require("mongoose");
const path = require("path"); // provide utilities for working with file and directory paths

const api = require("./api");

// Server configuration below
// TODO change connection URL after setting up your own database
const mongoConnectionURL =
"mongodb+srv://weblab:jAT4po55IAgYWQgR@catbook-ylndp.mongodb.net/test?retryWrites=true&w=majority";
// TODO change database name to the name you chose
const databaseName = "catbook";
const options = { useNewUrlParser: true, useUnifiedTopology: true, dbName: databaseName};

// connect to mongodb
mongoose
.connect(mongoConnectionURL, options)
.then(() => console.log("Connected to MongoDB"))
.catch((err) => console.log(`Error connecting to MongoDB: ${err}`));

// create a new express server
const app = express();
app.use(validator.checkRoutes);

// allow us to parse POST request data using middleware
app.use(express.json());

// connect user-defined routes
app.use("/api", api);

// load the compiled react files, which will serve /index.html and /bundle.js
const reactPath = path.resolve(__dirname, "..", "client", "dist");
app.use(express.static(reactPath));

// for all other routes, render index.html and let react router handle it
app.get("*", (req, res) => {
res.sendFile(path.join(reactPath, "index.html"));
});

// any server errors cause this function to run
app.use((err, req, res, next) => {
const status = err.status || 500;
if (status === 500) {
// 500 means Internal Server Error
console.log("The server errored when processing a request!");
console.log(err);
}

res.status(status);
res.send({
status: status,
message: err.message,
});
});

// hardcode port to 3000 for now
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port: ${port}`);
});