Note The database used in this document is the Bilibili_hot database provided by the tutorial. For details about how to download and import the data provided by the tutorial, see basics of MongoDB and Mongoose.

  • The related operations of MongoDB are performed at Mongosh
  • Mongoose operations are performed in the Node.js back-end service based on express.js

MongoDB

Create a document

Inserting a single document

Using the db.collection.insertone () method to insert a document into a collection, let’s switch to bilibili_hot and insert a data item in the mems collection:

> use bilibili_hot
switched to db bilibili_hot

> db.hotspots.insertOne({ "name": "This is a new piece of data" })
WriteResult({ "nInserted" : 1 })
Copy the code

You’ll notice that the inserted document data doesn’t tally with the existing document structure in our Mems collection, which doesn’t have a name and is far more complex than this document. This is actually what we talked about in the previous tutorial. Collections in MongoDB are dynamically modded, which means that the documents in a collection can be diverse (but not recommended).

Injects an item of data into a non-existing collection to get a better understanding of dynamic mode. Check that the current collection should only have one mems:

> show collections
hotspots
Copy the code

Then we insert a data item into the books collection:

> db.books.insertOne({ name: 'The Definitive Guide to MongoDB' })
WriteResult({ "nInserted" : 1 })
Copy the code

See all collections now:

> show collections
books
hotspots
Copy the code

If you have any experience with relational databases, you might think that inserting a piece of data should be preceded by creating a table. In MongoDB, that means creating a collection, whereas collections can be created dynamically.

Insert multiple documents

Multiple documents can be inserted into a collection using the db.collection.insertmany () method

> db.hotspots.insertMany([{ "title": "Video 1" }, { "title": "Video 2" }])

{
	"acknowledged" : true,
	"insertedIds" : [
		ObjectId("612afe521d4385df4950fd74"),
		ObjectId("612afe521d4385df4950fd75")]}Copy the code

From the return value, we can see that an insertedIds field is returned, with the data type ObjectId. This is because MongoDB automatically creates the _ID field for each document, with the data type ObjectId.

Other ways to insert documents

These are two of the most common ways to insert documents, but MongoDB actually provides other ways to do this that we won’t cover here. For those interested, see MongoDB Manu-Insert Methods in the 5.0 documentation on the official website.

  • db.collection.insert(): insertOne()andinsertMany()The shorthand
  • db.collection.update(): Need to set{upsert: true}options
  • db.collection.updateOne(): Need to set{upsert: true}options
  • db.collection.updateMany(): Need to set{upsert: true}options
  • db.collection.findAndModify(): Need to set{upsert: true}options
  • db.collection.findOneAndUpdate(): Need to set{upsert: true}options
  • db.collection.findOneAndReplace(): Need to set{upsert: true}options
  • db.collection.bulkWrite()

Delete the document

The db.collection.remove() method removes all documents in the collection, but not the collection itself. The remove() function can take a query condition as an argument, which, given as a secondary argument, will later remove documents that match the condition.

Let’s delete the document whose title is “design ghost” :

> db.hotspots.remove({ "title": "The schemer." })
WriteResult({ "nRemoved" : 70 })
Copy the code

As you can see, 70 documents in the collection have been deleted because we have 70 {“title”: “design ghost”} data in the collection (the deleted data is permanent and cannot be undone or restored).

Mongo also provides db. Collection. FindOneAndDelete () method is used to delete a document, and the collection, the remove (), the method will be deleted the document back to the client.

Let’s delete the last updated document whose title is “design ghost”. First let’s take a look at the date of the latest update:

> db.hotspots.find({ "title": "The schemer." }, { update_time: 1, _id: 0 }).sort( { update_time: - 1  } ).limit(1)
{ "update_time" : ISODate("The 2021-08-25 T02:00:00) 125 z")}Copy the code

Now we use the db. Collection. FindOneAndDelete () to delete the document:

> db.hotspots.findOneAndDelete({ "title": "The schemer." }, { sort: { update_time: - 1{}})"_id" : ObjectId("6125a42064ceb40e291801ac"),
	"title" : "The schemer."."update_time" : ISODate("The 2021-08-25 T02:00:00) 125 z"),
	"__v" : 0
}
Copy the code

You can see that the document with the latest update is deleted and returned.

Update the document

The content of update operation is relatively complex. MongoDB documents introduce four basic update methods, which are as follows:

  • db.collection.updateOne(<filter>, <update>, <options>)
  • db.collection.updateMany(<filter>, <update>, <options>)
  • db.collection.replaceOne(<filter>, <update>, <options>)
  • db.collection.update(<filter>, <update>, <options>)

Method takes the first argument to the query document, which locates the target document you want to update, the second argument to the update operator, which specifies the conditions for updating the document, and the third argument, which is optional.

Let’s start with the second argument, the use of the update operator. The first query document will be covered in the next section, but don’t worry, we will only use simple query criteria for now.

Update operator

For example, we want to make changes to the following document:

{
	"_id" : ObjectId("6123b52a64ceb40e2917c938"),
  "title" : "Hungry Ghost Festival chaoshan Culture short film 'Fanke' : I hope that every dead person will be commemorated, and everyone will eventually fall back to their roots."."update_time" : "The 2021-08-23 T14:3. 392 z"."stat" : {
      "aid" : 890021627."view" : 610680."danmaku" : 6934."reply" : 6116."favorite" : 31956."coin" : 63543."share" : 20852."now_rank" : 0."his_rank" : 71."like" : 68606."dislike" : 0}... }Copy the code

$set

We want to make the title shorter and change it to “Fan”, and change update_time to the latest time. We can use updateOne() method.

> db.hotspots.updateOne(
	{ "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$set": { "title": "Short Film of Chaoshan Culture in Hungry Ghost Festival"."update_time": new Date() } }  
)
Copy the code

Use findOne() to find the document:

> db.hotspots.findOne({ "_id": ObjectId("6123b52a64ceb40e2917c938") {})"_id" : ObjectId("6123b52a64ceb40e2917c938"),..."title" : "Short Film of Chaoshan Culture in Hungry Ghost Festival"."update_time" : ISODate("The 2021-08-31 T14:11:08. 560 z"),... }Copy the code

You can see that both the title and update_time fields have been successfully updated. This is the most common use of $set in business, changing a value in a document.

Currently, we use $set for fields that already exist in the document. If the field does not exist, $set creates it, for example, to set a new field.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$set": { "newkey": "New field"}})Copy the code

Looking at the document again, you have the new field newKey

> db.hotspots.findOne({ "_id": ObjectId("6123b52a64ceb40e2917c938") {})"_id" : ObjectId("6123b52a64ceb40e2917c938"),..."title" : "Short Film of Chaoshan Culture in Hungry Ghost Festival"."update_time" : ISODate("The 2021-08-31 T14:11:08. 560 z"),
  "newkey" : "New field". }Copy the code

The $set field can also change the value of the embedded document. For example, the stat.view in the document represents the number of videos played. The current number of videos played is 610680.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$set": { "stat.view": 610681}})Copy the code

$unset

$unset can be used to delete a field. Remember newkey? Let’s delete it

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$unset": { "newkey": 1}})Copy the code

$inc

$inc can be used to add or subtract numbers. Remember when we changed the stat view value from 610680 to 610681? We actually get the number of plays of the document first and then set the number of plays +1 to stat.view, but with $inc we can reduce the number of plays of the document.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$inc": { "stat.view": 1}})Copy the code

Trust me, by this time it’s almost 610,682 streams.

Here are two more coins for the up of this video:

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$inc": { "stat.coin": 2}})Copy the code

Or maybe the video went viral and moved up 10 places. The his_rank rank needs to be subtracted by 10 from 71

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$inc": { "stat.his_rank": - 10}})Copy the code

The following update operators are used in arrays. Let’s add a field called Danmaku to hold the barrage.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$set": { "danmaku": []}})Copy the code

$push

We can use $push to add the danmaku data to the danmaku field:

db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$push": { "danmaku": '666'}})Copy the code

If you look in the document at this point, you will see that we have successfully added a barrage of data

> db.hotspots.find({ "_id": ObjectId("6123b52a64ceb40e2917c938") {})"_id" : ObjectId("6123b52a64ceb40e2917c938"),
  "title" : "Short Film of Chaoshan Culture in Hungry Ghost Festival"."danmaku" : [ 
    "666"]}Copy the code

If we need to add more than one barrage, we can use the child operator $each

db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$push": { "danmaku": { "$each": [ "yyds"."Is tide shan words!!"."Tears in my eyes."]}}})Copy the code

If you want to maintain an array of fixed length, you can also use the suboperator $slice. The $slice value must be a negative integer, such as -10. If the array length is less than 10, all data is retained. If the value is greater than 10, only the last 10 entries are retained.

Danmaku now has 4 bullets

{
  "_id" : ObjectId("6123b52a64ceb40e2917c938"),..."danmaku": [ 
    "666"."yyds"."Is tide shan words!!"."Tears in my eyes."]}Copy the code

Let’s add two more pieces of data and set the maximum length of Danmaku to 5.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$push": { 
  	"danmaku": { 
    		"$each": [ "Too real!"."This is great!"]."$slice": - 5}}})Copy the code

At this time there are 5 danmaku barrage, the earliest one 666 is no longer there.

{
  "_id" : ObjectId("6123b52a64ceb40e2917c938"),..."danmaku": [ 
    "yyds"."Is tide shan words!!"."Tears in my eyes."."Too real!"."This is great!"]}Copy the code

$addToSet

You might use an array as a Set with unique elements, so you can use $addToSet instead of $push.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$addToSet": { "danmaku": "Too real!"}})Copy the code

The return value of this command is as follows:

{
  "acknowledged" : true,
  "matchedCount" : 1.0."modifiedCount" : 0.0
}
Copy the code

You can see that modifiedCount is 0, no value has been changed because danmaku already exists in danmaku, unless you insert data that is not in the array:

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$addToSet": { "danmaku": "How beautiful!"}})Copy the code

$popand$pullRemove elements

{“$pop”:{“key “:1}} from the end of the array, {“$pop”:{“key “:-1}} from the head.

> db.hotspots.updateOne(
	{ "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$pop": { "danmaku": 1}})Copy the code

Of course we can also use $pull to remove elements that specify conditions, for example let’s remove all YYds in the barrage.

> db.hotspots.updateOne(
  { "_id": ObjectId("6123b52a64ceb40e2917c938")}, {"$pull": { "danmaku": "yyds"}})Copy the code

Optional parameters

Let’s look at the third argument to the update method, which is an object that can be passed multiple arguments.

upsert

In real business, we often need to find out if this data exists in the collection before updating. Suppose we have a collection of fans that is dedicated to storing up master’s fan data. Update () will not find up data from fans if the initial number of fans is 0, so use findOne() to find up data first. If there is no up data, we need to create a document, if there is an update().

Is there a way to do this with just one statement? Yes, that’s upsert.

Upsert is a special update that creates a new document if no matching document is found, and updates normally if any matching document exists. Let’s use upsert to do what we just did, and at this point we don’t even have a collection of fans in our database.

db.fans.updateOne(
	{ "mid": 57938157 }, 
  { "$push": { "fan_list": "First fan."}}, {"upsert": true } 
)
Copy the code

Db.fans.find ({}) and you will find that the collection of fans has been created and a piece of data is available.

{
  "_id" : ObjectId("612f7e277784e59e5d640217"),
  "mid" : 57938157.0."fan_list" : [ 
      "First fan."]}Copy the code

Let’s add another fan to the up master’s list:

db.fans.updateOne(
  { "mid": 57938157 }, 
  { "$push": { "fan_list": "Second fan."}}, {"upsert": true } 
)
Copy the code

When db.fans.find() is executed again, there is still only one document in the collection:

{
    "_id" : ObjectId("612f7e277784e59e5d640217"),
    "mid" : 57938157.0."fan_list" : [ 
        "First fan."."Second fan."]}Copy the code

multi

When using db.collection.update(), only one document is updated by default. If multiple documents need to be updated, {“multi”: true} in the third parameter is required.

> db.hotspots.update(
  { "title": "Hungry Ghost Festival chaoshan Culture short film 'Fanke' : I hope that every dead person will be commemorated, and everyone will eventually fall back to their roots." },
  { "$set": { "title": "Short Film of Chaoshan Culture in Hungry Ghost Festival"."update_time": new Date() } },
  { "multi": true }
)

Updated 95 existing record(s) in 88ms
Copy the code

By executing the command above, you can see that we have updated the titles of 95 documents.


Mongoose

Create a document

Create schemas and models

In the previous tutorial, we introduced the basic concepts of Mongoose. First, we need to create a Schema and a Model. In Mongoose, most CRUD operations are Model methods. We export the Model we created as a HotSpot. Js file for easy use.

// HotSpot.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const hotSpotSchema = new Schema({
  aid: {
    type: Number.required: true,},videos: {
    type: Number.default: 1,},tid: {
    type: Number.default: 0,},tname: {
    type: String.require: true,},copyright: {
    type: Number.dafault: 1,},pic: {
    type: String,},title: {
    type: String.require: true,},pubdate: {
    type: Date,},ctime: {
    type: Date.require: true,},desc: {
    type: String.default: "",},state: {
    type: Number,},duration: {
    type: Number.default: 0,},owner: {
    mid: {
      type: Number,},name: {
      type: String,},face: {
      type: String,}},stat: {
    aid: {
      type: Number,},view: {
      type: Number,},danmaku: {
      type: Number,},reply: {
      type: Number,},favorite: {
      type: Number,},coin: {
      type: Number,},share: {
      type: Number,},now_rank: {
      type: Number,},his_rank: {
      type: Number,},like: {
      type: Number,},dislike: {
      type: Number,}},dynamic: {
    type: String,},cid: {
    type: Number,},dimension: {
    width: {
      type: Number,},height: {
      type: Number,},rotate: {
      type: Number,}},short_link: {
    type: String,},short_link_v2: {
    type: String,},first_frame: {
    type: String,},bvid: {
    type: String,},season_type: {
    type: Number,},rcmd_reason: {
    content: {
      type: String,},corner_mark: {
      type: Number,}},update_time: {
    type: Date,}});const HotSpot = mongoose.model("hotSpot", hotSpotSchema);

module.exports = HotSpot;
Copy the code

Inserting a single document

Method 1: use ** model.create ()**

Use Model.create() to insert single or multiple documents, let’s insert a document in Mems:

HotSpot.create({ title: "true" }, function(err, raw) {
  if (err) {
    console.log(err)
    return
  }
  console.log(raw)
})
Copy the code

When you execute this code, you will find the following error

Error: hotSpot validation failed: aid: Path `aid` is required.
...
Copy the code

Error message: aid should be mandatory. We defined the key {required: true} in the Schema, but there is no aid in the inserted object.

new Schema({
  aid: {
    type: Number.required: true,}... })Copy the code

With the existence of Schema in Mongoose, the problem of inconsistent document data structure in the same set that MongoDB may encounter due to dynamic mode can be avoided. Let’s take the data from inserting a compliant hotspot video:

const validData = {
  videos: 1.tid: 172.desc: "The pony and the old horse game is ready, but I don't think anyone will play it. Let's go play Outcast.".duration: 387.aid: 377533236.tname: "Mobile Games".copyright: 1.pic: "http://i2.hdslb.com/bfs/archive/2d95711a493730101d977f60f641ab32b576c49d.jpg".title: "The schemer.".pubdate: new Date("The 1970-01-19 T20:42:02. 595 z"),
  ctime: new Date("The 1970-01-19 T20:42:02. 596 z"),
  state: 0.owner: {
    mid: 1577804.name: "Some phantom king.".face: "http://i2.hdslb.com/bfs/face/a7eda2f97431d13f89a43b310262d1b19be83c01.jpg",},stat: {
    aid: 377533236.view: 251936.danmaku: 4851.reply: 2986.favorite: 8022.coin: 15046.share: 563.now_rank: 0.his_rank: 0.like: 47592.dislike: 0,},dynamic: "Design genius.".cid: 395302606.dimension: {
    width: 1920.height: 1080.rotate: 0,},short_link: "https://b23.tv/BV19f4y1P7FL".short_link_v2: "https://b23.tv/BV19f4y1P7FL".first_frame:
    "http://i2.hdslb.com/bfs/storyff/n210823a23kjji9eu348m3eernmihnbp_firsti.jpg".bvid: "BV19f4y1P7FL".season_type: 0.rcmd_reason: {
    content: "Lots of likes.".corner_mark: 0,},update_time: new Date("The 2021-08-23 T14:3. 392 z"),}; HotSpot.create(validData,function(err, raw) {
  if (err) {
    console.log(err)
    return
  }
  console.log(raw)
})
Copy the code

Method 2: use **document.save()**

The instance of the Model constructor is a document, and we can also insert a single document using the document.save() method

const hotSpotDoc = new HotSpot(validData);

hotSpotDoc.save(function (err, raw) {
  if (err) {
    console.log(err);
    return;
  }
  console.log(raw);
});
Copy the code

Insert multiple documents

Model.insertmany () can insert multiple documents

HotSpot.insertMany([validData, validData], function(err, raw) {
  if (err) {
    console.log(err)
    return err
  }
  console.log(raw)
})
Copy the code

Delete the document

Let me take a look at how to delete a document using Mongoose. Mongoose provides the model.deleteone () method to delete a document. And model.deletemany () delete multiple documents.

Let’s delete the data with the title “League of Legends 10th Anniversary” :

const raw = await HotSpot.deleteOne(
  { title: "League of Legends 10th anniversary."});console.log(raw)
/ / {
// deletedCount: 1
// }
Copy the code

Mongoose also provides two other methods that can be used for deletion:

  • Model.findOneAndDelete(): Looks for matching documents to delete, and passes any documents found in, if any, to the callback function
  • Model.findByIdAndDelete(): through documentation_idDelete delete it, yesModel.findOneAndDelete({ _id: id })The abbreviation of

Let’s use model.findoneandDelete () to delete a document that was updated last and whose title is still “League of Legends 10th anniversary”. Start by looking at the existing update times in your shell

> db.hotspots.find({ title: "League of Legends 10th anniversary."  }, {update_time: 1, _id: 0{})"update_time" : ISODate("The 2021-08-25 T17:30:00. 137 z")} {"update_time" : ISODate("The 2021-08-25 T18:00:00) 146 z")} {"update_time" : ISODate("The 2021-08-25 T18:30:00. 140 z")} {"update_time" : ISODate("The 2021-08-25 T19:00:00) 147 z")}Copy the code

Delete with model.findoneandDelete () :

const raw = await HotSpot.findOneAndDelete(
  { title: "League of Legends 10th anniversary." },
  { sort: { update_time: - 1}}); console.log(raw)Copy the code

Let’s take a look at the existing update time in the shell again:

> db.hotspots.find({ title: "League of Legends 10th anniversary."  }, {update_time: 1, _id: 0{})"update_time" : ISODate("The 2021-08-25 T17:30:00. 137 z")} {"update_time" : ISODate("The 2021-08-25 T18:00:00) 146 z")} {"update_time" : ISODate("The 2021-08-25 T18:30:00. 140 z")}Copy the code

You can see that the latest data has been deleted.

Update the document

Mongoose provided three basic methods for updating documents, which were basically the same as the document operation in MonGOSH. The three methods were as follows:

  • Model.update()
  • Model.updateMany()
  • Model.updateOne()

We updated a document {“title”: “Design genius”} to {“title”: “Design genius”}.

const raw = await HotSpot.updateOne(
  { title: "The schemer." },
  { $set: { title: "Design genius."}})console.log(raw)

/ / {
// acknowledged: true,
// modifiedCount: 1,
// upsertedId: null,
// upsertedCount: 0,
// matchedCount: 1,
// }
Copy the code

We can also update all {“title”: “setup”} documents with the updateMany() method:

const raw = await HotSpot.updateMany(
  { title: "The schemer." },
  { $set: { title: "Design genius.".update_time: new Date()}})console.log(raw)

/ / {
// acknowledged: true,
// modifiedCount: 69,
// upsertedId: null,
// upsertedCount: 0,
// matchedCount: 69,
// }
Copy the code

You can see that the return value modifiedCount: 69 indicates that 69 entries have been updated.

We can also use update(), but note that model.update () differs from db.collection.update() in Mongosh. Model.update() in Mongoose will change all matching documents by default, while in Mongosh, {“multi”: true} will change all documents. Let’s restore the title field:

const raw = await HotSpot.update(
  { title: "Design genius." },
  { $set: { title: "The schemer." , update_time: new Date()}})console.log(raw)

/ / {
// acknowledged: true,
// modifiedCount: 70,
// upsertedId: null,
// upsertedCount: 0,
// matchedCount: 70,
// }
Copy the code

According to the result of the return value, the titles of 70 documents have been updated to their original names.

Let’s take the number of views +1 and the number of coins +2:

const raw = await HotSpot.update(
  { title: "The schemer." },
  { $inc: { "stat.view": 1."stat.coin": 2}})console.log(raw)

/ / {
// acknowledged: true,
// modifiedCount: 70,
// upsertedId: null,
// upsertedCount: 0,
// matchedCount: 70,
// }
Copy the code

Since the operation of update operators such as Mongoose is the same as that of Mongosh, we do not have more examples here, readers can refer to the previous text.

other

The resources

  1. The Mongoose’s official website
  2. Directing a website