JavaScript 进阶营饥人谷技术博客程序员

Mongoose 基本操作

2018-01-19  本文已影响0人  _Dot912

前提


核心

名词解释

三者关系
Schema 生成 Model,Model 创造 Entity,Model 和 Entity 都可以对数据库进行操作,但 Model 比 Entity 更具操作性


应用

首先要知道,数据库的所有操作都是异步的。

基本操作

结合代码使用

# test.js
const mongoose = require('mongoose')
mongoose.Promise = global.Promise// 最好加上这句话
const Schema = mongoose.Schema
const log = console.log
const err = console.error

// 创建连接,因为数据库操作是异步的,使用then方法可保证连接之后才执行操作
const db = mongoose.connect('mongodb://localhost/test').then(() => {
    // Schema和Model变量名大写,entity变量名小写,集合名小写,如cats
    const CatSchema = Schema({ name: String }) // Schema

    const CatModel = mongoose.model('cats', CatSchema)  //Model

    const catEntity = new CatModel({ name: 'Dolb' })  //实体 entity
      
    //以下所有逻辑都在这里进行

})
    // 增
    catEntity.save((e,res)=>{
        if(e){
            err(e)
        }else{
            log('save suc')
        }
    })

这里我运行node test.js保存成功后退出程序并再次node test.js

运行两次node test.js

得到的是几条数据呢?

查看数据条目

得到了两条数据,结论是数据库的数据没有覆盖一说,哪怕内容相同,重复save只会重复添加。

为了方便后面的演示,将const catEntity = new CatModel({ name: 'Dolb' })中的name值分别改为MiaoMimi,这样数据库下的cats集合里就有以下四条数据:

当前数据

另外补充一下,使用Model来新增数据使用create方法,如:CatModel.create({name: 'Dot'} , callback)

    // 增
    catEntity.save((e, res) => {
        if (e) {
            err(e)
        } else {
            log('save suc')
        }
    })

    // 删除新增的Mimi的数据
    catEntity.remove({ name: 'Mimi' }, (e, res) => {
        if (e) {
            err(e)
        } else {
            log('remove Mimi suc')
        }
    })

运行node 结果

是不是和想象的完全不一样?那么怎样做到删除当前增加的条目呢?

    // 增
    catEntity.save((e, res) => {
        if (e) {
            err(e)
        } else {
            log('save suc')
            // 删除新增的Mimi的数据
            catEntity.remove({ name: 'Mimi' }, (e, res) => {
                if (e) {
                    err(e)
                } else {
                    log('remove Mimi suc')
                }
            })
        }
    })

将删除的代码放进增加的代码中,就可以保证删除在新增之后执行

运行node 数据

可以看到仍是5条数据,说明新增的Mimi被删除了,事实上remove的第一个参数不写就可以做到删除当前条目了:

    // 增
    catEntity.save((e, res) => {
        if (e) {
            err(e)
        } else {
            log('save suc')
            // 删除新增的Mimi的数据
            catEntity.remove((e, res) => {
                if (e) {
                    err(e)
                } else {
                    log('remove Mimi suc')
                }
            })
        }
    })

数据

可是假设现在我们需要删除所有name为Dolb的数据,又该怎么做呢?这个时候就要用到Model了⬇️

    // 删除所有符合name值为Dolb的数据
    CatModel.remove({ name: 'Dolb' }, (e, res) => {
        if (e) {
            err(e)
        } else {
            log('remove Dolb suc')
        }
    })
数据
    CatModel.remove((e, res) => {
        if (e) {
            err(e)
        } else {
            log('remove Dolb suc')
        }
    })

这里为了接下来的操作就不执行这段代码了

    CatModel.find({ name: 'Mimi' }, (e, res) => {
        if (e) {
            err(e)
        } else {
            log('find Mimi suc: There have ' + res)
        }
    })
    CatModel.find((e, res) => {
        if (e) {
            err(e)
        } else {
            log('find all cats suc: There have ' + res)
        }
    })
数据

到这里我误删了所有数据,所以重新新建的数据如下:

现在的数据
    CatModel.update({ name: 'Miao' }, { name: 'Miao2' }, (e, res) => {
        if (e) {
            err(e)
        } else {
            log('更新成功')
            // 只更新一个
            CatModel.updateOne({ name: 'Miao2' }, { name: 'Miao3' }, (e, res) => {
                if (e) {
                    err(e)
                } else {
                    log('更新第一个Miao成功')
                }
            })
        }
    })

    CatModel.updateMany({ name: 'Mimi' }, { name: 'Mimi2' }, (e, res) => {
        if (err) {
            err(err)
        } else {
            log('更新成功')
        }
    })
加入updateOne前后,数据的变化

所以update和updateMany有什么区别呢?


进阶
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const log = console.log
const err = console.error

// Plugin插件,用来更新Schema的功能
// 全局Plugin,更新全部Schema的功能,全局plugin最好放在靠前的位置
// 以下代码为所有操作打上时间戳
function TimePlugin(schema, options) {
    const str = 'save time'
    schema.pre('save', next => {
        console.time(str)
        next()
    })
    schema.post('save', next => {
        console.timeEnd(str)
    })
}
mongoose.plugin(TimePlugin)

const PostSchema = new Schema({
    title: {
        type: String,
        // Validation  验证器 验证存入数据库的数据
        // 验证器,validate是放在Schema下的字段用来做字段限制的
        validate: {
            validator: v => v.length < 10,
            message: '文章标题长度必须小于10'
        }
    },
    author: {
        type: Schema.Types.ObjectId,
        ref: 'User'
    },
    rawContent: String,
    create_at: {
        type: Date,
        default: Date.now
    },
    update_at: {
        type: Date,
        default: Date.now
    },
    comments: {
        type: Array
    },
    votes: Number,
    downs: Number
})

const UserSchema = new Schema({
    name: String,
    sex: Number,
    avatar: String,
    mail: String,
    password: String
})

const CommentSchema = new Schema({
    author: {
        type: Schema.Types.ObjectId,
        required: true
    },
    content: {
        type: 'string',
        required: true
    },
    postId: {
        type: Schema.Types.ObjectId,
        required: true
    }
})

const PostModel = mongoose.model('Post', PostSchema)
const UserModel = mongoose.model('User', UserSchema)
const CommentModel = mongoose.model('Comment', CommentSchema)

const db = mongoose.connect('mongodb://localhost/dolb').then(() => {

    // 1. 插入文章
    function addPost(post) {
        const postEntity = new PostModel(post)
        postEntity.save((e, result) => {
            if (e) {
                err(e)
            } else {
                log('保存成功啦')
                //    getPostByTitle('hello world')// 插入之后才能查到文章,而操作都是异步的,不能保证顺序,所以调用getPostByTitle放在addPost里能保证查得到
            }
        })
    }
    addPost({
        title: 'hello wo'
    })

    // 2. 根据id删除文章
    function removePostById(postId) {
        PostModel.remove({ _id: postId }, (e, res) => {
            if (e) {
                err(e)
            } else {
                log('删除所有id为...成功啦')
            }
        })
    }
    // removePostById('5a609fba3906973fc61f640b')

    // 3. 根据文章标题查找文章
    function getPostByTitle(title) {
        PostModel.find({ title }, (e, res) => {
            if (e) {
                err(e)
            } else {
                log(res)
            }
        })
    }

    // 4.更新文章
    function updatePost(id, title) {
        PostModel.update({ _id: id }, { title }, (e, res) => {
            if (e) {
                err(e)
            } else {
                log(res)
            }
        })
    }
    // updatePost('5a60a17d951bc340519c0e95','hey dolby')
})

// middleware中间件
PostSchema.pre('save', next => {
    log('hey i am pre hook')
    next()
})
PostSchema.post('save', next => {
    log('hey i am post hook')
})

执行现有的代码,得到:

hey i am pre hook
save time: 9.787ms
hey i am post hook
保存成功啦

证明钩子优先级大于自身回调


常见报错


实践结论


查询Mongoose API

上一篇 下一篇

猜你喜欢

热点阅读