本項目基於: egg.jshtml
npm install egg-mongoose --save
# /config/plugin.ts import { EggPlugin } from 'egg'; const plugin: EggPlugin = { mongoose: { enable: true, package: 'egg-mongoose', }, }; export default plugin;
# /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
eggjs 在 /app/model/ 下定義數據模型sql
以個人 blog 項目爲例,假設有一個 tag 表、article 表,article 表經過 tag_id 關聯 tag 表以下:mongodb
# /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); };
經過 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
新增一篇文章bash
# article 爲對象 const article: Article; this.ctx.model.Article.create(article);
批量新增
# article 爲數組 const article: Array<Article>; this.ctx.model.Article.create(article);
刪除一篇文章
this.ctx.model.Article.deleteOne(search);
刪除多篇文章
this.ctx.model.Article.remove(search);
查找一篇文章
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個數據
替換文章內容
# 注意,是直接所有替換爲 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 對指定文檔中的某些鍵進行更新,若是這個字段不存在則建立它
# 修改文章 pv爲 10000 const operation: any = { $set: { pv: 10000, }, }; return await this.ctx.model.Article.findOneAndUpdate(search, operation);
# 查pv大於10的文章 const search = { pv: { $gt: 1000, }, }; this.ctx.model.Article.find(search);
查找 pv 大於 10 且公開的文章
const search: any = { $and: [ { pv: { $gt: 10 } }, { status: true }, ], }; this.ctx.model.Article.find(search);
$inc 用來增長和減小已有鍵的值,只能用於 Number 類型。對於不存在的鍵,會自動建立相應的鍵,而且值爲給定的值
文章 pv 自增
const operation: any = { $inc: { pv: 1, }, }; this.ctx.model.Article.findOneAndUpdate(search, operation);
$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 相似與 js Araay includes 方法,與數組中任意一個值相等
查找 pv 在[1,2,3]的文章
const search: any = { pv: { $in: [ 1, 2, 3 ], }, }; this.ctx.model.Article.find(search);
$type 匹配數據類型
詳細的類型請:MongoDB $type 操做符
匹配 status 字段類型爲 boolean
const search: any = { status: { $type: 8, }, }; this.ctx.model.Article.find(search);
$exists 判斷字段是否存在
查找 status 字段存在的文章
const search: any = { status: { $exists: true, }, }; this.ctx.model.Article.find(search);
$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 相似於 mysql 的 where
查找 pv 大於 20 的文章
const search: any = { $where: 'this.pv>20', }; this.ctx.model.Article.find(search);
MongoDB 的聚合管道將 MongoDB 文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。
經常使用的管道操做符:
$match 用於過濾數據,只輸出符合條件的文檔。
this.ctx.model.Article.aggregate([ { $match: search }, ]);
$project 用於修改輸入文檔的結構,能夠用來重命名、增長或刪除域
修改文檔結構,只輸出 content 字段
this.ctx.model.Article.aggregate([ { $match: search }, { $project: { content: 1, }, }, ]);
經常使用的分頁查找
this.ctx.model.Article.aggregate([ { $match: search }, { $skip: page_size * (current_page - 1) }, { $limit: page_size }, ]);
$group 將集合中的文檔分組,用於統計結果。相似於 mysql group by
統計每一個標籤的文章總數 count
this.ctx.model.Article.aggregate([ { $group: { _id: '$tag_id', count: { $sum: 1, }, }, }, ]);
$sort 將輸入文檔排序後輸出
按照文章修改時間倒序
this.ctx.model.Article.aggregate([ { $match: search }, { $sort: { updated_time: -1 } }, ]);
有幾個參數:
語法 | 解釋 |
---|---|
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