mongoose操作mongodb - Go语言中文社区

mongoose操作mongodb


1、安装

npm install mongoose -S

2、引入mongoose及链接mongodb数据库

链接时特别注意几点:

(1)参数一是 mongodb。(2)路径中间不能有空格。

(3)后边的mongo_test 是要连接的数据库的名称,如果没有该数据库,会创建。

(4)如果有账号和密码可以在 mongodb://账号:密码@localhost:27017/mongo_test 添加,后边用@区分。

// 连接本地mongodb服务器
let connect = mongoose.connect('mongodb://localhost:27017/mongo_test',{useNewUrlParser: true})
.then(res => {
    console.log('连接成功++++++++++++++++',res)
})

3、三个重要概念:

(1)Schema: 数据库储存格式的约定协议,可理解为数据表的字段类型声明

常用的字段类型: String、Number、Date、Buffer(二进制)、Boolean、Mixed(混合类型,就是啥都可以存储)、ObjectId(对象id)、Array

// 主要用于定义db中集合里document文档的结构
let userSchema = new mongoose.Schema({
    name: String,
    age: {
        type: Number,
        default: 20
    }
})

(2)Model : 由Schema转化的数据模型,具有抽象属性和行为的数据库操作,可以进行查询操作。

let User = mongoose.model('User', userSchema)
let userInstance = new User({
    name: '吕星辰'
})

(3)instance: 由Model创建的实体操作对象,可以对数据库进行完整的CRUD(增删改查)操作。

(4)关于字段的一些属性:

type:字段的类型;

require:true或false,指定该字段是否必填(默认false,不是必填的);

max与min:数字,只能用在Number类型,可以表示最大值与最小值是多少;

maxlength与minlength:只能用于String字符串类型,表示最长或最短字符串长度;

enum:  ['男', '女'],可枚举类型,后边是一个数组,也就是值必须在枚举值中,并且枚举类型必须是String;

    例:sex: { type: String, enum: [ '男', '女' ] } sex字段的值必须在枚举值中,且必须为字符串。

defalt: 'xxx', 默认值,如果没有传参数时,会取默认值,存入数据库。

trim: true, 去除字符串两端空格(保存前对字段进行 .trim())

uppercase:true , 只能用于字符串,表示把所有小写字母转为大写字母(保存前对字段进行.toUpperCase())

lowercase:true , 只能用于字符串,表示把所有大写字母转为小写字母(保存前对字段进行.toLowerCase())

     例:test{ type: String, lowercase: true }。

select: true/false,指定该字段在查询出的数据中是否显示,true表示查询数据过滤该字段;

get: () => {} 和set:() => {},两个函数使用Object.defineProperty( ) 来定义getter、setter。

validate: ()=>{ } ,为该字段添加校验。

 

(5)关于Mixed

一个啥都可以放的SchemaType,非常便利,但是不太好维护,Mixed可以通过:Schema.Types.Mixed 或 一个空对象来定义,下边三种效果一致:

mongoose.Schema({any: {}})
mongoose.Schema({any: Object})
mongoose.Schema({ any: Schema.Types.Mixed })

 

 

4、一个简单的小例子

连接mongodb,声明一个Schema模型

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mongo_test', {userNewUrlParser: true})
.then(r => {
    console.log('连接成功:', r)
})
// 声明一个Schema模型,定义用户名和年龄
let Schema = mongoose.Schema;
let userSchema = new Schema({
    name: String,
    age: {
        type: Number,
        default: 20
    }
})

将声明的Schema转化为Model,  并将Model实例转化为Instance

// mongoose.model('User', userSchema, 'userName') 参数三是设置数据集的名称,默认是参数一的小写负数形式。
// 相当于mysql中的表名。。。。
let User = mongoose.model('User', userSchema);
// 平时开发,一般是把上边User导出去,然后再路由文件中引入。 module.export = {User}
let userInstance = new User({
    name: '吕星辰'
})
// 把数据保存到数据库
uesrInstance.save((err, res) => {
    if(err) {
        console.log(err)
    }
    console.log('保存成功, 插入的数据为', res)
})

上边的 userInstance 可以进行数据库的增删改查操作,执行上边代码:

打开navicat,显示的数据如下(我之前已经插入好多数据了):

注意:

 _id 每一个文档document都会被mongoose添加一个不重复的 _id,  _id 的数据类型不是字符串,而是ObjectID类型。如果在查询语句中要使用_id,则需要使用findById语句。而不能使用find或findOne语句。

 

常用API:

下边方法返回的是一个promise

增:

1、插入单条(两种方法):

// 下边User是mongoose.model('User', Schema) 创建的
// 方法一:
const user = new User({ name: 'xxx', age: 20 });
user.save().then(r => {
    console.log('新增成功,新增的数据为:', r)
})
// 方法二:
User.create({
    name: 'xxx', age: 20
}).then(r => {
    console.log('新增成功,新增的数据为:', r)
})
// 输出结果为:{ name: 'xxx', age: 20, _id: 6073e2897f6a8d3b18170792, __v: 0 }

2、插入多条:

User.insertMany(arr, callback) 或 User.insertMany(arr).then().catch()

// 插入多条数据
User.insertMany([{username: '111'}, {username: '222'}]).then(r => {
    console.log('保存成功:', r)
}).catch(err => {
    console.log('保存失败:', err)
})

打印结果:

查:

(1)User.find( ) 查询全部数据

(2)User.find( {name: 'xxx'}, [options] ) 根据某个字段来查询, 参数二可选对象,可以过滤字段

例1:

User.find().then(r => {
    console.log('查询全部数据: ', r)
})

例2:

// 跳过前6条数据,查询剩余的数据
User.find(null, null, {skip: 6}).select("username age")

(2.1)控制字段,

把字段设置为true,表示显示的字段,设置为false,表示隐藏的字段, _id默认会被输出,如果不想被输出,设置为false即可。

const r = await User.find({username: '吕星辰'}, {username: true})
console.log("res:", r)

(2.2)过滤字段,

还可以在后边添加 select() 方法, 参数可以是数组、对象、字符串:

// 下边三种过滤字段的方法:

// select参数可以是数组或对象,查询出的数据只显示username和password
await User.find({username: '吕星辰'}).select(['username', 'password'])
// select参数为对象
await User.find({username: '吕星辰'}).select({username: true, password: true})
// select参数为字符串(字段之间以空格隔开)
await User.find({username: '吕星辰'}).select('username password')

(2.3)还有种方式是select('+xxx +xxx') 或select('-xxx -xxx'),注意多个字段中间以空格隔开+ 意思是包含xxx字段,- 的意思是过滤掉xxx字段。

例:

// 后边要有select属性
const UserSchema = mongoose.Schema({
    username: {type: String, default: '吕星辰', select: false},
    password: {type: String, selelct: false},
    name: String
})
User = mongoose.model('User', UserSchema, 'user')
User.find({username: '吕星辰'}).select("+password -username -name")

(3)User.findOne({ id: xxx }) 获取单条数据

(4)常用的约束条件查询

        4.1、where() 过滤查询

        User.where( ) 或 user.find( ).where( )

// 例1:查询年龄大于20小于60的数据 :
     User.find().where("age").gte(20).lte(60) 
// 等同于:
     User.find({age: {$gte: 20, $lte: 60}})
// 例2:查询age为50的数据 :
     User.where('age', 50)

         4.2、or() 或

// or参数为数组
// 查询年龄为20或30的数据
User.find().or([{ age: 20 }, { age: 30 }]) 

         4.3、nor() 不是xx 或 xx的数据

// 查询年龄不为20或30的数据
User.find().nor([{ age: 20 }, { age: 30 }]) 

         4.4、and() 且

// 查询username为"吕星辰" 且 password为 '1231'
await User.find().and([{username: '吕星辰'}, {password: '1231'}]).select("username")

         4.5、gt() 大于、gte() 大于等于

        注:使用 gt()或 gte()必须使用where作为查询字段

// 查询username为"吕星辰" 且 password为 '1231'
await User.find().where("age").gte(32).select("username age")

         4.6、lt() 小于、lte() 小于等于

        注:使用 lt()或 lte()必须使用where作为查询字段

---------------------------------------------------------------------------------------------------------------------------------------

特定方法:

         4.7、sort( ) 排序

// 按照age从小到大排序
await User.find().sort('age').select("username age")
// 按照age从大到小排序
await User.find().sort('-age').select("username age")

         4.8、skip( ) 跳过

// 跳过前2条数据,输出余下的数据
await User.find().skip(2).select("username age")

         4.9、limit( ) 限制

// 获取前2条数据
await User.find().limit(2).select("username password mobile")

         4.10、select( ) 控制显示字段

         4.11、exect( ) 执行

         4.12、count( ) 计数

await User.find().count()

         4.13、distinct( ) 去重

 

创建实例方法

通过创建出来的Schame在模型的实例上定义实例方法:

// user.js
const mongose = rquire('mongoose');
const UserSchema = mongose.Schema({})
// 添加一个实例方法,特别注意:this.model('User') User参数是模型的名称,也就是在
// mongose.model('User')参数一中定义的User
UserSchema.methods.findByUserName = async function(username) {
    return await this.model('User').findOne({username}) 
}
exports.User = mongose.model('User', UserSchema)

// 在路由中使用findByUserName方法
const user = new User();
// 通过实例username方法查询
user.findByUserName('吕星辰').then(res => {
    console.log('res:', res)
}).catch(err => console.log("err:", err))

(4)也可以添加静态方法,通过User来获取静态方法,同上。

 

改:

(2.1)修改单个数据:

User.update({ id: 1 }, { name: 'xxx' }) 

把id为1的数据中的name改为 xxx

User.update({n_name: '吕星辰'}, {n_name: '吕星辰111'}).then(r => {
    console.log('r: ',r )
})

(2.2)修改单个数据:

User.updateOne({ id: 1 }, { name: 'xxx' }) 

把id为1的数据中的name改为 xxx

(2.3)修改一条数据中的多个字段值:

User.updateMany({ id: 1 }, { name: 'xxx', age:20 })

把id为1的数据中的name改为 xxx,age更改为 20

 

补充:

1、有时候查询的时候需要忽略某个字段,比如:密码等敏感字段。可以在创建Schema的时候,在字段后边加上 select: true,这样查询时mongoose会自动过滤掉此字段。

const schema = mongoose.Schema({
    name: { type: String, require: true },
    password: {
        type: String, require: true, select: true
    }
})

2、mongoose使用的时间类型会自动转化为格林尼治时间(零时区的时间)。而我们当前的时区为东八区,换算成零时区需要将我们的时间减去八小时,如果你贸然的把时间加上八小时,这种操作会返回一个错误的时间,因为世界各地转化为格林尼治标准的时差不同。

解决此问题,安装: moment-timezone

如果你知道用户所在的时区,可以使用 moment.tz.guess( ) 来获取当前时区:

const moment = require('moment-timezone');
moment('2021-04-08 02:31:29.859').tz("Asia/Shanghai").format("YYYY年MM月DD日 HH:mm:ss")
// 输出结果为: 2021年04月08日 02:31:29

//猜测时区: moment.tz.guess()  -> Asia/Shanghai

3、新增数据前的处理

schema.pre( )

在mongoose.Schema( ) 时,我们会拿到创建好的schema, 它上边有一个pre钩子方法,此钩子会在save保存之前执行:

注:必须调用next() 方法才能执行保存操作,否则不会执行任何以外操作。

const UserSchema = mongoose.Schema({
    name: { type: String }
})
UserSchema.pre('save', function(next) {
    console.log('新数据为:', this) // this为保存的新数据
    next()
})

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_42778001/article/details/115396597
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-14 18:52:51
  • 阅读 ( 1295 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢