Usage Summary of egg Mongoose

preface

This project is based on: egg.js

Installation configuration

1. installation dependency

npm install egg-mongoose --save

2. open the plug-in

# /config/plugin.ts
import { EggPlugin } from 'egg';

const plugin: EggPlugin = {
  mongoose: {
    enable: true,
    package: 'egg-mongoose',
  },
};

export default plugin;

3. plug in configuration

# /config/config.default.ts
import { EggAppConfig, PowerPartial } from 'egg';

export default () => {
  const config = {} as PowerPartial<EggAppConfig>;

  config.mongoose = {
    url: process.env.MONGO_URL || 'mongodb://localhost:27017/blog',
    options: {
      poolSize: 40,
    },
  };

  return {
    ...config,
  };
};

The lock environment of the project:

"egg-mongoose": "3.2.0"

node -v
v10.5.0

Split line, the following is the key point

apply

I Create Model

eggjs defines the data model under /app/model/

Take my blog project as an example. Suppose there is a tag table and an article table. The article table passes through the tag_ The ID associated tag table is as follows:

1.tag table

# /app/model/tag.ts
module.exports = app => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;
  const PostSchema = new Schema({
    tag_name: {
      type: String,
      required: true,
    },
    created_time: {
      type: Date,
      default: new Date(),
    },
    updated_time: {
      type: Date,
      default: new Date(),
    },
  });
  return mongoose.model('Tag', PostSchema);
};

2.article table

Via tag_id Association tag table

# /app/model/article.ts
module.exports = app => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;
  const PostSchema = new Schema({
    tag_id: {
      type: Schema.Types.ObjectId,
      required: true,
      ref: 'Tag',
    },
    title: {
      type: String,
      required: true,
    },
    status: {
      type: Boolean,
      default: false,
    },
    content: {
      type: String,
      default: '',
    },
    weather: {
      type: String,
      default: '',
    },
    image: {
      type: String,
      default: '',
    },
    images: {
      type: Array,
      default: [],
    },
    pv: {
      type: Number,
      default: 0,
    },
    created_time: {
      type: Date,
      default: new Date(),
    },
    updated_time: {
      type: Date,
      default: new Date(),
    },
  });
  return mongoose.model('Article', PostSchema);
};

More schema usage: mongoose schema

II Simple and common

In eggjs, the model layer is generally operated in the service layer, and a promise is returned. so you can directly use await for synchronous programming

Let's first define search as the query condition

1. increase

Add an article

# article as object
const article: Article;
this.ctx.model.Article.create(article);

Batch add

# article is an array
const article: Array<Article>;
this.ctx.model.Article.create(article);

2. delete

Delete an article

this.ctx.model.Article.deleteOne(search);

Delete multiple articles

this.ctx.model.Article.remove(search);

3. check

Find an article

this.ctx.model.Article.findOne(search);

Find multiple articles

# search is empty or the empty object returns all
this.ctx.model.Article.find(search);

Paging lookup skip, limit

this.ctx.model.Article.find(search)
  .sort({ _id: -1 }) # In reverse order of creation time
  .skip(page_size * (current_page - 1)) # Skip the first n data
  .limit(page_size); # Limit n data

4. change

Replace article content

# Note that it is to directly replace all with new_data
# findOneAndUpdate returns old data by default
# If a partial update is required, the $set operator should be used
return await this.ctx.model.Article.findOneAndUpdate(search, new_data);

Return the latest modified data

# Note the third parameter
return await this.ctx.model.Article.findOneAndUpdate(search, new_data, { new: true });

Split the line again, and the following are the key points in the key points

III Operator

&dollar;set

&Dollar; Set updates some keys in the specified document, and creates this field if it does not exist

# Modify the article pv to 10000
const operation: any = {
  $set: {
    pv: 10000,
  },
};
return await this.ctx.model.Article.findOneAndUpdate(search, operation);

$gt,$lt,$gte,$lte,&dollar;ne

  • (>) greater than &dollar; gt
  • (<) less than &dollar; lt
  • (> =) greater than or equal to &dollar; GTE
  • (< =) less than or equal to &dollar; LTE
  • (! = =) is not equal to &dollar; NE
# Check articles with pv greater than 10
const search = {
  pv: {
    $gt: 1000,
  },
};
this.ctx.model.Article.find(search);

$or,$and,$not,$nor

  • &Dollar; Or satisfies any expression
  • &Dollar; And satisfies multiple expressions at the same time
  • &Dollar; Not does not satisfy the expression
  • &Dollar; Nor does not satisfy any expression

Find public articles with pv greater than 10

const search: any = {
  $and: [
    { pv: { $gt: 10 } },
    { status: true },
  ],
};
this.ctx.model.Article.find(search);

&dollar;inc

&Dollar; Inc is used to increase and decrease the value of existing keys. It can only be used for Number type. For keys that do not exist, the corresponding key is automatically created and the value is the given value

Article pv self increment

const operation: any = {
  $inc: {
    pv: 1,
  },
};
this.ctx.model.Article.findOneAndUpdate(search, operation);

&dollar;push,&dollar;pull

&Dollar; Push adds an element to the end of an existing array. If not, it creates a new array

&Dollar; Pull will delete the qualified elements in the array

const operation: any = {
  $push: {
    images: {
      content: 'hello world',
    },
  },
};
await this.ctx.model.Article.findOneAndUpdate(search, operation);

const operation: any = {
  $pull: {
    images: {
      content: 'hello world',
    },
  },
};
await this.ctx.model.Article.findOneAndUpdate(search, operation);

&dollar;in,&dollar;nin

  • &Dollar; In contains
  • &Dollar; NIN does not contain

&Dollar; In is similar to the js Araay includes method and is equal to any value in the array

Find articles on pv in [1,2,3]

const search: any = {
  pv: {
    $in: [ 1, 2, 3 ],
  },
};
this.ctx.model.Article.find(search);

&dollar;type

&Dollar; Type matches the data type

For detailed types: Mongodb &dollar; Type operator

The matching status field type is boolean

const search: any = {
  status: {
    $type: 8,
  },
};
this.ctx.model.Article.find(search);

&dollar;exists

&Dollar; Exists determines whether the field exists

Find articles where the status field exists

const search: any = {
  status: {
    $exists: true,
  },
};
this.ctx.model.Article.find(search);

&dollar;regex

&Dollar; Regex regular matching content

Regular matching content 123

const search: any = {
  content: { $regex: '123', $options: 'i' },
};
this.ctx.model.Article.find(search);

In fact, you can also use literal quantity directly

const search: any = {
  content: /123/g,
};
this.ctx.model.Article.find(search);

&dollar;where

&Dollar; Where is similar to where in mysql

Find articles with pv greater than 20

const search: any = {
  $where: 'this.pv>20',
};
this.ctx.model.Article.find(search);

IV Aggregate aggregate

The MongoDB aggregation pipeline passes the MongoDB document to the next pipeline for processing after one pipeline is processed. Pipe operations can be repeated.

Common pipe operators:

1.&dollar;match

&Dollar; Match is used to filter data and only output documents that meet the conditions.

this.ctx.model.Article.aggregate([
  { $match: search },
]);

2.&dollar;project

&Dollar; Project is used to modify the structure of the input document. It can be used to rename, add or delete fields

Modify the document structure and output only the content field

this.ctx.model.Article.aggregate([
  { $match: search },
  {
    $project: {
      content: 1,
    },
  },
]);

3.&dollar;limit,&dollar;skip

  • &Dollar; Limi: limit the number of returned documents
  • &Dollar; Skip: skip a specified number of documents

Common paging lookup

this.ctx.model.Article.aggregate([
  { $match: search },
  { $skip: page_size * (current_page - 1) },
  { $limit: page_size },
]);

4.&dollar;group

&Dollar; Group groups the documents in the collection for statistical results. Similar to mysql group by

count the total number of articles per tag

 this.ctx.model.Article.aggregate([
  {
    $group: {
      _id: '$tag_id',
      count: {
        $sum: 1,
      },
    },
  },
]);

5.&dollar;sort

&Dollar; Sort sorts the input documents and outputs them

Reverse the revision time of the article

this.ctx.model.Article.aggregate([
  { $match: search },
  { $sort: { updated_time: -1 } },
]);

6.&dollar;lookup,&dollar;unwind

  • &Dollar; Unwind splits an Array type field into multiple pieces, each containing a value in the Array
  • &Dollar; Lookup mongo3.2 is a new version, which is used to implement associated table query

There are several parameters:

grammar explain
from Source Datasheet
localField Data sheet to be joined
foreignField match field of data table of Join
as Name the new increment for the output document

Find the article details according to the tag_id to find the details of the tag table

this.ctx.model.Article.aggregate([
  {
    $lookup: {
      from: 'tags',
      localField: 'tag_id',
      foreignField: '_id',
      as: 'tag_info',
    },
  },
  { $unwind: '$tag_info' },
]);

END

Tags: node.js Back-end Front-end MongoDB Mongoose

Posted by Coinnoch on Tue, 31 May 2022 10:25:53 +0530