egg-mongoose使用總結

前言

本項目基於: egg.jshtml

安裝配置

1.安裝依賴

npm install egg-mongoose --save

2.開啓插件

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

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

export default plugin;

3.插件配置

# /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,
  };
};

本項目鎖使用的環境:node

"egg-mongoose": "3.2.0"

node -v
v10.5.0

分割線,下面是重點mysql

使用

一.建立 Model(模型)

eggjs 在 /app/model/ 下定義數據模型sql

以個人 blog 項目爲例,假設有一個 tag 表、article 表,article 表經過 tag_id 關聯 tag 表以下:mongodb

1.tag 表

# /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 表

經過 tag_id 關聯 tag 表npm

# /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);
};

更多 schema 使用:mongoose schema編程

二.簡單經常使用

eggjs 中,通常在 service 層操做 model 層,返回的是一個 promise,so 能夠直接用 await 同步編程數組

咱們先定義 search 爲查詢條件promise

1.增

新增一篇文章bash

# article 爲對象
const article: Article;
this.ctx.model.Article.create(article);

批量新增

# article 爲數組
const article: Array<Article>;
this.ctx.model.Article.create(article);

2.刪

刪除一篇文章

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

刪除多篇文章

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

3.查

查找一篇文章

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

查找多篇

# search 爲空 或者空對象返回所有
this.ctx.model.Article.find(search);

分頁查找 skip、limit

this.ctx.model.Article.find(search)
  .sort({ _id: -1 }) # 按照建立時間倒序
  .skip(page_size * (current_page - 1)) # 跳過前n個數據
  .limit(page_size); # 限制n個數據

4.改

替換文章內容

# 注意,是直接所有替換爲 new_data
# findOneAndUpdate默認返回舊的數據
# 若須要部分更新,應使用 $set 操做符
return await this.ctx.model.Article.findOneAndUpdate(search, new_data);

返回修改後最新的數據

# 注意第三個參數
return await this.ctx.model.Article.findOneAndUpdate(search, new_data, { new: true });

再次分割線,下面是重點中的重點

三.操做符

$set

$set 對指定文檔中的某些鍵進行更新,若是這個字段不存在則建立它
# 修改文章 pv爲 10000
const operation: any = {
  $set: {
    pv: 10000,
  },
};
return await this.ctx.model.Article.findOneAndUpdate(search, operation);

$gt、$lt、$gte、$lte、$ne

  • (>) 大於 $gt
  • (<) 小於 $lt
  • (>=) 大於等於 $gte
  • (<= ) 小於等於 $lte
  • (!==) 不等於 $ne
# 查pv大於10的文章
const search = {
  pv: {
    $gt: 1000,
  },
};
this.ctx.model.Article.find(search);

$or、$and、$not、$nor

  • $or 知足任一表達式
  • $and 同時知足多個表達式
  • $not 不知足表達式
  • $nor 不知足任一表達式

查找 pv 大於 10 且公開的文章

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

$inc

$inc 用來增長和減小已有鍵的值,只能用於 Number 類型。對於不存在的鍵,會自動建立相應的鍵,而且值爲給定的值

文章 pv 自增

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

$push、$pull

$push 向已有的數組末尾添加一個元素,若是沒有就建立一個新的數組

$pull 會刪除掉數組中符合條件的元素

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);

$in、$nin

  • $in 包含
  • $nin 不包含
$in 相似與 js Araay includes 方法,與數組中任意一個值相等

查找 pv 在[1,2,3]的文章

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

$type

$type 匹配數據類型

詳細的類型請:MongoDB $type 操做符

匹配 status 字段類型爲 boolean

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

$exists

$exists 判斷字段是否存在

查找 status 字段存在的文章

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

$regex

$regex 正則匹配內容

正則匹配內容 123

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

實際上,也能夠直接用字面量

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

$where

$where 相似於 mysql 的 where

查找 pv 大於 20 的文章

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

四.aggregate 聚合

MongoDB 的聚合管道將 MongoDB 文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。

經常使用的管道操做符:

1.$match

$match 用於過濾數據,只輸出符合條件的文檔。
this.ctx.model.Article.aggregate([
  { $match: search },
]);

2.$project

$project 用於修改輸入文檔的結構,能夠用來重命名、增長或刪除域

修改文檔結構,只輸出 content 字段

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

3.$limit、$skip

  • $limi: 限制返回的文檔數
  • $skip:跳過指定數量的文檔

經常使用的分頁查找

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

4.$group

$group 將集合中的文檔分組,用於統計結果。相似於 mysql group by

統計每一個標籤的文章總數 count

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

5.$sort

$sort 將輸入文檔排序後輸出

按照文章修改時間倒序

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

6.$lookup、$unwind

  • $unwind 將 Array 類型字段拆分紅多條,每條包含數組中的一個值
  • $lookup mongo3.2 版本新增,用於實現聯表查詢

有幾個參數:

語法 解釋
from 源數據表
localField 待 Join 的數據表
foreignField Join 的數據表的 match 字段
as 爲輸出文檔的新增值命名

查找文章詳情,根據 tag_id 查找 tag 表的詳情

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

END

相關文章
相關標籤/搜索