用Mongoose进行CRUD工作的教程

501 阅读8分钟

在本教程中,我们将在Node.js和MongoDB环境中使用Mongoose来创建、读取、更新和删除数据库中的文档。我们将涵盖使用Mongoose连接到MongoDB,探索MongoDB模式,并审查MongoDB中的模型。从那里我们将继续保存文档,以及使用比较和逻辑表达式查询文档。我们还将看到如何使用Mongoose的查询优先和更新优先方法来更新文档。也将包括使用Mongoose从数据库中删除文档。现在让我们开始用Mongoose进行CRUD工作。


用Mongoose连接到MongoDB

我们可以从一个新的项目结构开始使用MongoDB。在这里,我们运行mkdir mongo-crudcd mongo-crud ,然后是npm init --yes ,以初始化一个新的项目来工作。
mongo crud directory

现在让我们通过输入npm i mongoose ,使用npm包管理器安装Mongoose。Mongoose是一个MongoDB对象建模工具,设计用于在异步环境中工作。
npm i mongoose

现在我们可以继续在Visual Studio Code或你最喜欢的IDE程序中打开mongo-crud文件夹。
visual studio code mongodb

我们准备使用这段代码从Node.js连接到MongoDB
index.js

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/mongo-games')
    .then(() => 'You are now connected to Mongo!')
    .catch(err => console.error('Something went wrong', err))

我们使用nodemon启动index.js,然后我们得到了一个大麻烦!我们忘了启动Mongo数据库。
mongodb connection failure

mongo-crud $nodemon index.js[nodemon] 1.17.5
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node index.js`
Something went wrong { Error: write ECONNABORTED
    at _errnoException (util.js:1022:11)
    at Socket._writeGeneric (net.js:767:25)
    at Socket._write (net.js:786:8)
    at doWrite (_stream_writable.js:387:12)
    at writeOrBuffer (_stream_writable.js:373:5)
    at Socket.Writable.write (_stream_writable.js:290:11)
    at Socket.write (net.js:704:40)
    at Connection.write (C:nodemongo-crudnode_modulesmongodb-corelibconnectionconnection.js:733:57)
    at C:nodemongo-crudnode_modulesmongodb-corelibconnectionpool.js:1571:44
    at waitForAuth (C:nodemongo-crudnode_modulesmongodb-corelibconnectionpool.js:1425:40)
    at C:nodemongo-crudnode_modulesmongodb-corelibconnectionpool.js:1433:5
    at C:nodemongo-crudnode_modulesmongodb-corelibconnectionpool.js:1286:23
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)
  name: 'MongoNetworkError',
  message: 'write ECONNABORTED',
  stack: 'Error: write ECONNABORTEDn    at _errnoException (util.js:1022:11)n
   at Socket._writeGeneric (net.js:767:25)n    at Socket._write (net.js:786:8)n    at doWrite (_stream_writable.js:387:12)n    at writeOrBuffer (_stream_writable.js:373:5)n    at Socket.Writable.write (_stream_writable.js:290:11)n    at Socket.write (net.js:704:40)n    at Connection.write (C:\node\mongo-crud\node_modules\mongodb-core\lib\connection\connection.js:733:57)n    at C:\node\mongo-crud\node_modules\mongodb-core\lib\connection\pool.js:1571:44n
  at waitForAuth (C:\node\mongo-crud\node_modules\mongodb-core\lib\connection\pool.js:1425:40)n    at C:\node\mongo-crud\node_modules\mongodb-core\lib\connection\pool.js:1433:5n    at C:\node\mongo-crud\node_modules\mongodb-core\lib\connection\pool.js:1286:23n    at _combinedTickCallback (internal/process/next_tick.js:131:7)n    at process._tickCallback (internal/process/next_tick.js:180:9)' }
[nodemon] clean exit - waiting for changes before restart

我们忘了启动Mongo Daemon。让我们在命令提示符下运行mongod ,启动MongoDB。一旦完成,我们可以再试着连接一次,现在事情看起来好多了。
mongoose connected to mongodb

完美了我们已经在一个Node项目中安装了Mongoose,并且我们能够连接到我们之前安装的Mongo数据库


Mongodb模式

为了开始在MongoDB中插入数据的工作,我们需要创建一个Schema。在MongoDB的背景下,什么是模式?Schema定义了MongoDB中一个集合中的文档形状。MongoDB中的集合就像关系数据库世界中的。在一个集合中,你可以有一个或多个文档。MongoDB中的文档有点类似于基于SQL的数据库中的行。集合有许多文档,就像表有许多行。每个文档是一个键/值对的容器。让我们看看如何在Mongoose中创建一个模式。

const gameSchema = new mongoose.Schema({
    title: String,
    publisher: String,
    tags: [String],
    date: {
        type: Date,
        default: Date.now
    },
    onSale: Boolean,
    price: Number
});

我们想在Mongo数据库中插入一个新游戏,所以我们需要先在Mongoose中定义数据的模式。这正是我们在上面的代码中所做的。以下是代码的作用。

  • gameSchema 在MongoDB中定义游戏文档的形状
  • new mongoose.Schema({}) 创建一个Mongoose Schema类的新实例,其中传入一个对象。
  • title: String 每个游戏都需要一个标题,它是一个字符串值。
  • publisher: String 每个游戏也有一个出版商,也是一个字符串值。
  • tags: [String] 我们可以给一个游戏分配多个标签,每个标签都是一个字符串。
  • date: { type: Date, default: Date.now } 在插入游戏时,我们想包括一个日期值。
  • onSale: Boolean 该游戏目前是否在销售?是或不是(真或假),用一个布尔值表示。
  • price: Number 最后,每个游戏都有一个价格--用一个数字表示。

当创建模式时,可以使用的类型有:字符串、数字、日期、缓冲区、布尔值、ObjectID和数组。


Mongodb中的模型

在这一点上,我们已经清楚地定义了一个游戏在被添加到Mongo数据库中时应该是什么。换句话说,我们有了一个定义游戏文档形状的Schema,将其添加到MongoDB的一个集合中。这个模式现在必须被编译成一个模型。你可以把MongoDB中的Model看作是给定Schema的一个实例。这与在面向对象编程中从一个类中创建一个新的对象的想法相同。下面是我们如何创建一个模型。

const Game = mongoose.model('Game', gameSchema);

Mongoose提供了model()方法,它接受两个参数。第一个参数是你的模型的集合的单数名称。按照惯例,Mongoose会自动寻找你的模型名称的复数版本。因此,在上面的代码中,模型'Game'是用于数据库中的'games'集合。model()方法的第二个参数是模式,它定义了这个集合中的文档的形状。这在我们的应用程序中给了我们一个新的Game 类。这就是为什么在上面那行代码中,我们要把调用mongoose.model()的结果分配给那个Game常量。它被大写了,因为这里存储的是一个类,而不是一个对象。

既然这是一个类,我们可以从这个类中新建一个对象。看看吧。

const game = new Game({
    title: "The Legend of Zelda: Breath of the Wild",
    publisher: "Nintendo",
    tags: ["adventure", "action"],
    onSale: false,
    price: 59.99,
});

我们上面所做的是创建一个新的Game类的实例,并在实例化过程中传递一个对象。我们可以简单地设置该对象的属性,就像我们想的那样。这是在准备将这个文件保存到Mongo数据库。来回顾一下到目前为止所涉及的步骤。

  • 使用mongoose.Schema()定义一个模式
  • 使用该结果来创建一个模型,使用mongoose.model()
  • 你现在有一个可以创建实例(对象)的类。
  • 这些对象映射到MongoDB数据库中的文档

在MongoDB中保存(创建)一个文档

我们已经做了所有的工作,将这个文档保存到数据库中。你可能觉得我们所要做的就是像game.save(); ,然后我们就可以了。这几乎是真的。由于我们是在处理异步JavaScript,我们需要考虑到这一点,并利用回调、承诺或异步等待的方式。在下面的代码中,我们使用了async/await方法。注意,突出显示的代码定义了一个**saveGame()**的异步函数。在该函数中,我们使用了 await 关键字来表示我们在等待 Promise 的结果。最后,我们在代码的最后调用saveGame()函数。

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/mongo-games')
    .then(() => console.log('Now connected to MongoDB!'))
    .catch(err => console.error('Something went wrong', err));

const gameSchema = new mongoose.Schema({
    title: String,
    publisher: String,
    tags: [String],
    date: {
        type: Date,
        default: Date.now
    },
    onSale: Boolean,
    price: Number
});

const Game = mongoose.model('Game', gameSchema);

async function saveGame() {
    const game = new Game({
        title: "The Legend of Zelda: Breath of the Wild",
        publisher: "Nintendo",
        tags: ["adventure", "action"],
        onSale: false,
        price: 59.99,
    });

    const result = await game.save();
    console.log(result);
}

saveGame();

在命令行上运行应用程序,我们可以看到游戏已经被创建了!我们还可以浏览这个新的文档。

mongo-crud $node index.js
Now connected to MongoDB!
{ tags: [ 'adventure', 'action' ],
  _id: 5b1588507bd7b004ac79206b,
  title: 'The Legend of Zelda: Breath of the Wild',
  publisher: 'Nintendo',
  onSale: false,
  price: 59.99,
  date: 2018-06-04T18:43:28.423Z,
  __v: 0 }

我们现在还可以使用Compass浏览MongoDB中的这个新文档。
new document saved in mongo

你是否注意到,我们从来都不需要手动创建数据库,也没有像你在关系数据库系统中必须做的那样提前手动创建任何表。在MongoDB中,你只需创建一个文档,然后将其存储在数据库中。这是一个非常灵活的系统。在上面的例子中,通过简单地在连接字符串中包括 "mongo-games",一旦我们保存了一个文档,就会自动为我们创建一个数据库。现在,如果你愿意,就去把文档的值改为插入,这样我们就可以有很多游戏可以使用。然后我们可以对这些文档进行查询练习。


在MongoDB中查询(读取)文档

在前面的章节中添加了一些游戏后,我们现在可以从数据库中读取它们。在MongoDB中,有很多方法可以查询数据。我们可以从简单的find()方法开始。在下面的代码中,我们创建了一个名为getGames()的新异步函数。在该函数中,我们要获取数据库中的所有游戏。

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/mongo-games')
    .then(() => console.log('Now connected to MongoDB!'))
    .catch(err => console.error('Something went wrong', err));

const gameSchema = new mongoose.Schema({
    title: String,
    publisher: String,
    tags: [String],
    date: {
        type: Date,
        default: Date.now
    },
    onSale: Boolean,
    price: Number
});

const Game = mongoose.model('Game', gameSchema);

async function getGames() {
    const games = await Game.find();
    console.log(games);
}

getGames();

代码看起来不错,所以我们运行我们的节点应用程序。正如你所看到的,我们得到一个所有游戏的列表。

mongo-crud $node index.js
Now connected to MongoDB!
[ { tags: [ 'adventure', 'action' ],    _id: 5b1588507bd7b004ac79206b,
    title: 'The Legend of Zelda: Breath of the Wild',
    publisher: 'Nintendo',    onSale: false,
    price: 59.99,    date: 2018-06-04T18:43:28.423Z,
    __v: 0 },
  { tags: [ 'adventure', 'action' ],
    _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    publisher: 'Nintendo',
    onSale: true,
    price: 45,
    date: 2018-06-04T20:47:29.661Z,
    __v: 0 },
  { tags: [ 'racing', 'sports' ],
    _id: 5b15a5c610cf6b30dcdec47d,
    title: 'Mario Kart 8 Deluxe',
    publisher: 'Nintendo',
    onSale: false,
    price: 59.99,
    date: 2018-06-04T20:49:10.180Z,
    __v: 0 },
  { tags: [ 'action', 'shooter' ],
    _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    publisher: 'Nintendo',
    onSale: true,
    price: 35.99,
    date: 2018-06-04T20:51:17.812Z,
    __v: 0 },
  { tags: [ 'side scroller', 'platformer' ],
    _id: 5b15a6783863d22508a9703d,
    title: 'Rayman Legends',
    publisher: 'Ubisoft',
    onSale: false,
    price: 49.99,
    date: 2018-06-04T20:52:08.460Z,
    __v: 0 },
  { tags: [ 'simulation', 'farming' ],
    _id: 5b15a6ba75eabb4234ee9446,
    title: 'Stardew Valley',
    publisher: 'Chucklefish',
    onSale: false,
    price: 19.99,
    date: 2018-06-04T20:53:14.535Z,
    __v: 0 },
  { tags: [ 'adventure', 'platformer' ],
    _id: 5b15a6efa42bc928702bd749,
    title: 'Shovel Knight: Treasure Trove',
    publisher: 'Yacht Club Games',
    onSale: true,
    price: 10.99,
    date: 2018-06-04T20:54:07.257Z,
    __v: 0 } ]

向find()传递一个过滤器

现在我们想对结果进行一些过滤。我们可以通过传递一个对象来做到这一点。我们可以传入一个对象,其出版商属性设置为任天堂,而onSale属性设置为true。我们只想看到由任天堂发行的游戏,而且还在销售。下面是更新后的代码,可以做到这一点。

async function getGames() {
    const games = await Game.find({
        publisher: 'Nintendo',
        onSale: true
    });
    console.log(games);
}

getGames();

现在,我们可以再次在命令行中运行,我们看到了《超级马里奥奥德赛》和《Splatoon 2》--这两款游戏都在销售。很好!

mongo-crud $node index.js
Now connected to MongoDB!
[ { tags: [ 'adventure', 'action' ],
    _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    publisher: 'Nintendo',
    onSale: true,
    price: 45,
    date: 2018-06-04T20:47:29.661Z,
    __v: 0 },
  { tags: [ 'action', 'shooter' ],
    _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    publisher: 'Nintendo',
    onSale: true,
    price: 35.99,
    date: 2018-06-04T20:51:17.812Z,
    __v: 0 } ]

在查询中添加一个sort()

比方说,你想对结果进行排序。在我们的例子中,让我们按价格对这两个游戏进行排序。我们想把价格最低的游戏放在前面。我们可以向sort()方法传递一个对象,其价格属性设置为1。1表示升序,而-1表示降序。

async function getGames() {
    const games = await Game
        .find({ publisher: 'Nintendo', onSale: true })
        .sort({ price: 1 });

    console.log(games);
}

getGames();

这给了我们想要的结果,我们可以看到Splatoon 2的价格是35.99,在结果列表中排在第一位。

mongo-crud $node index.js
Now connected to MongoDB!
[ { tags: [ 'action', 'shooter' ],
    _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    publisher: 'Nintendo',
    onSale: true,
    price: 35.99,
    date: 2018-06-04T20:51:17.812Z,
    __v: 0 },
  { tags: [ 'adventure', 'action' ],
    _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    publisher: 'Nintendo',
    onSale: true,
    price: 45,
    date: 2018-06-04T20:47:29.661Z,
    __v: 0 } ]

只选择某些属性

我们并不真的需要看到每个文件的每一个属性,让我们只显示游戏的标题和价格。我们可以通过在查询中添加一个select()来做到这一点。我们再次传递一个对象,并将我们想要包括的属性设置为1。

async function getGames() {
    const games = await Game
        .find({ publisher: 'Nintendo', onSale: true })
        .sort({ price: 1 })
        .select({ title: 1, price: 1 });

    console.log(games);
}

getGames();

现在我们看到,我们只在查询结果中得到标题和价格。文档的id仍然包括在内,因为这就是MongoDB的工作方式。

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    price: 35.99 },
  { _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    price: 45 } ]

比较查询操作符

MongoDB有几个用于查询的比较运算符。

  • $eq匹配与给定值相等的值。
  • $ne匹配所有不等于给定值的值。
  • $gt匹配大于给定值的值。
  • $gte为大于或等于给定值的值提供匹配。
  • $lt将小于给定值的值进行匹配。
  • $lte用于匹配小于或等于给定值的值。
  • $in匹配一个数组中的任何一个值。
  • $nin匹配数组中没有的值。

有了这些知识,让我们找到所有小于25美元的游戏。我们通过向find()函数中的价格属性传递一个对象来实现这一目标。

async function getGames() {
    const games = await Game
        .find({ price: { $lt: 25 } })
        .sort({ price: 1 })
        .select({ title: 1, price: 1 });

    console.log(games);
}

getGames();

我们还可以使用in操作符检查数据库中的几个特定值。我们只想要正好是19.9935.9959.99的游戏。只要像这样向in操作符检查数据库中的几个特定值。我们只想要正好是19.99、35.99或59.99的游戏。只要像这样向in属性传递一个数组就可以了。

async function getGames() {
    const games = await Game
        .find({ price: { $in: [19.99, 35.99, 59.99] } })
        .sort({ price: 1 })
        .select({ title: 1, price: 1 });

    console.log(games);
}

getGames();

这个查询看起来效果很好!

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a6ba75eabb4234ee9446,
    title: 'Stardew Valley',
    price: 19.99 },
  { _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    price: 35.99 },
  { _id: 5b1588507bd7b004ac79206b,
    title: 'The Legend of Zelda: Breath of the Wild',
    price: 59.99 },
  { _id: 5b15a5c610cf6b30dcdec47d,
    title: 'Mario Kart 8 Deluxe',
    price: 59.99 } ]

这可能看起来有点令人困惑,因为你会期望像price < 25 ,就像你在基于sql的世界中可能看到的那样。在Mongo中,price < 25 被替换为类似price: { $lt: 25 } 的东西。语法不同,结果相同。当运行该程序时,我们可以看到我们有两个游戏的价格低于25美元。

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a6efa42bc928702bd749,
    title: 'Shovel Knight: Treasure Trove',
    price: 10.99 },
  { _id: 5b15a6ba75eabb4234ee9446,
    title: 'Stardew Valley',
    price: 19.99 } ]

让我们修改一下查询,现在给我们提供任何在10到50美元之间的游戏。我们通过在传递给price的对象中指定两个属性来做到这一点。

async function getGames() {
    const games = await Game
        .find({ price: { $gt: 10, $lt: 50 } })
        .sort({ price: 1 })
        .select({ title: 1, price: 1 });

    console.log(games);
}

getGames();

现在我们有5个游戏返回。所有这些游戏的价格都高于每场10美元,但低于每场50美元。

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a6efa42bc928702bd749,
    title: 'Shovel Knight: Treasure Trove',
    price: 10.99 },
  { _id: 5b15a6ba75eabb4234ee9446,
    title: 'Stardew Valley',
    price: 19.99 },
  { _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    price: 35.99 },
  { _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    price: 45 },
  { _id: 5b15a6783863d22508a9703d,
    title: 'Rayman Legends',
    price: 49.99 } ]

逻辑查询操作符

现在让我们来看看一些逻辑运算符。想象一下,我们想看所有由任天堂出版的游戏,或者,所有正在销售的游戏。我们怎样才能做到这一点呢?我们在查询链中使用.or()函数,像这样。

async function getGames() {
    const games = await Game
        .find()
        .or([{ publisher: 'Nintendo' }, { onSale: true }])
        .sort({ price: 1 })
        .select({ publisher: 1, title: 1, onSale: 1 });

    console.log(games);
}

getGames();

我们得到了我们正在寻找的结果。所有列出的游戏要么是由任天堂出版的,要么是正在销售的。只要每个游戏满足其中一个条件,那么它就会被包括在结果中。

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a6efa42bc928702bd749,
    title: 'Shovel Knight: Treasure Trove',
    publisher: 'Yacht Club Games',
    onSale: true },
  { _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    publisher: 'Nintendo',
    onSale: true },
  { _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    publisher: 'Nintendo',
    onSale: true },
  { _id: 5b1588507bd7b004ac79206b,
    title: 'The Legend of Zelda: Breath of the Wild',
    publisher: 'Nintendo',
    onSale: false },
  { _id: 5b15a5c610cf6b30dcdec47d,
    title: 'Mario Kart 8 Deluxe',
    publisher: 'Nintendo',
    onSale: false } ]

现在让我们在查询中添加另一个条件。我们想要所有由任天堂出版的游戏,或者,所有正在销售的游戏,并且,它们必须低于50美元。

async function getGames() {
    const games = await Game
        .find()
        .or([{ publisher: 'Nintendo' }, { onSale: true }])
        .and([{ price: { $lt: 50 } }])
        .sort({ price: 1 })
        .select({ publisher: 1, title: 1, onSale: 1, price: 1 });

    console.log(games);
}

getGames();

我们可以看到,我们已经成功地完善了查询。我们得到了更少的游戏,因为任何超过50美元的游戏现在都被排除在外。

mongo-crud $node index.js
Now connected to MongoDB!
[ { _id: 5b15a6efa42bc928702bd749,
    title: 'Shovel Knight: Treasure Trove',
    publisher: 'Yacht Club Games',
    onSale: true,
    price: 10.99 },
  { _id: 5b15a645a28b042f0822271f,
    title: 'Splatoon 2',
    publisher: 'Nintendo',
    onSale: true,
    price: 35.99 },
  { _id: 5b15a561d34346325cd8e564,
    title: 'Super Mario Odyssey',
    publisher: 'Nintendo',
    onSale: true,
    price: 45 } ]

MongoDB中的更新(Update)

现在我们开始使用Mongoose更新MongoDB中的文档。有几种方法可以做到这一点,我们将看一下这两种方法。


使用查询优先来更新文档

在查询优先的方法中,你首先使用**.findById()**找到文档的id。然后修改任何你喜欢的属性,最后再调用.save()函数。你可能对这种方法相当熟悉,因为它在所有的语言和框架中都基本相同。下面是我们如何做到这一点的。

async function updateGame(id) {
    const game = await Game.findById(id);
    if (!game) return

    game.price = 24;

    const result = await game.save();
    console.log(result);
}

在上面的代码中,我们通过游戏的唯一ID找到它。如果有些事情不成功,或者我们没有正确的id,函数就直接返回。否则,我们更新价格,将其设置为24美元。最后我们保存游戏并输出结果。所以我们追踪我们的塞尔达游戏的ID,发现它是5b1588507bd7b004ac79206b。让我们像这样对该函数进行调用。

updateGame('5b1588507bd7b004ac79206b');

当我们运行应用程序时,我们现在看到这个游戏的价格是24美元。非常好!

mongo-crud $node index.js
Now connected to MongoDB!
{ tags: [ 'adventure', 'action' ],
  _id: 5b1588507bd7b004ac79206b,
  title: 'The Legend of Zelda: Breath of the Wild',
  publisher: 'Nintendo',
  onSale: false,
  price: 24,
  date: 2018-06-04T18:43:28.423Z,
  __v: 0 }

使用 "先更新 "来更新一个文档

在使用Mongoose时,也有一种更新优先的方法。在这种方法中,你只需潜入数据库并直接更新文档。你也可以在完成后返回更新的文档。这种方法利用了.update()方法。

async function updateGame(id) {
    const result = await Game.update({ _id: id }, {
        $set: {
            title: 'A Link Between Worlds',
            price: 55
        }
    });
    console.log(result);
}

updateGame('5b1588507bd7b004ac79206b');

当我们运行程序时,我们会看到一个文档被更新了。

mongo-crud $node index.js
Now connected to MongoDB!
{ n: 1, nModified: 1, ok: 1 }

当我们用Compass检查这个文档的数据时,我们可以看到它起作用了。它现在有一个新的标题以及一个新的价格。
update first mongodb mongoose

如果你确实想看到更新后的文档,你可以使用.findByIdAndUpdate(),就像我们在这里看到的。

async function updateGame(id) {
    const game = await Game.findByIdAndUpdate({ _id: id }, {
        $set: {
            title: 'Ocarina of Time ',
            price: 35
        }
    }, { new: true });
    console.log(game);
}

updateGame('5b1588507bd7b004ac79206b');
mongo-crud $node index.js
Now connected to MongoDB!
{ tags: [ 'adventure', 'action' ],
  _id: 5b1588507bd7b004ac79206b,
  title: 'Ocarina of Time ',
  publisher: 'Nintendo',
  onSale: false,
  price: 35,
  date: 2018-06-04T18:43:28.423Z,
  __v: 0 }

在MongoDB中移除(删除)文档

终于到了!我们可以看到如何使用Mongoose从MongoDB中删除一个文档。我们将使用.deleteOne()方法来实现这一目的。

async function deleteGame(id) {
    const result = await Game.deleteOne({ _id: id })
    console.log(result);
}

deleteGame('5b1588507bd7b004ac79206b');

当运行应用程序时,它显示我们有一个文档被删除。

mongo-crud $node index.js
Now connected to MongoDB!
{ n: 1, ok: 1 }

如果我们在Compass中查看,现在只有6个文档,而我们开始时有7个。删除是成功的。
mongoose delete document


Mongoose Crud教程总结

综上所述,在使用Mongoose在MongoDB中执行crud操作时,需要记住一些关键点。

  • 在你可以在MongoDB中存储对象之前,你需要首先定义一个Mongoose模式
  • 模式定义了MongoDB中文档的形状
  • 模式类型(SchemaType)对象用于提供关于数据的细节。
  • 你可以使用的类型有。字符串数字日期缓冲区布尔值ObjectID
  • 一旦定义了mongoose模式,它必须被编译成一个模型
  • 一个模型类似于一个类。它是一个创建对象的蓝图。
  • 有用的方法有:.save(),.findById(),.set(), .update(),.findByIdAndUpdate(), .deleteOne(),.deleteMany(), 和**.findByIdAndRemove(**)。