带你梳理Mongoose模块下MongoDB中的进阶操作

带你梳理Mongoose模块下MongoDB中的进阶操作

为确保下面的内容是有意义的,请保证在阅读前保证对mongoose模式下的MongoDB数据库的增删改查(CURD)有清晰的理解和认识,如果对mongoose模块下数据库增删改查没有熟练掌握,请务必捋清楚基础概念,多次尝试

准备工作

后文中的model基于以下的schema创建

var UserSchema = mongoose.Schema({
	name:String,
	sex:String,
    age:Number,
	job:String,
	email:String,
	phoneNumber:String,
});

var userModel = mongoose.model('User',UserSchema);

Mongoose 预定义模式修饰符

​ 在创建schema的时候,一般是这样写的

……
name:String,
age:Number,
……

想要字段后面跟上数据类型(SchemaTypes)

(我们顺便来复习一下)
以下是 mongoose 的所有合法 SchemaTypes:
String
Number
Date
Buffer
Boolean
Mixed
ObjectId
Array
Decimal128

其实对于我们后期实例化(model)以后增加数据的时候,可以对增加的数据进行一些格式上的规范

name:{
	type:String,
	trim:true,
	lowercase: true
}

age:{
	type:Number,
	default:1
}

你可以直接声明 schema type 为某一种 type,或者赋值一个含有 type 属性的对象,而我们对于格式的规范就写在这个对象里

下面我们来介绍一下几个常见的预定义模式修饰符

trim修饰符

我们在某些网站创建账号的时候,经常会遇到重名的情况,网站往往是不允许重名的

比如有人叫:小张同学。而有些人也想在这个网站取这名字,就会尝试在这个名字后面加几个空格,空格也算字符

比如:(空格)小张同学(空格)(空格)(空格)ps:以为自己很聪明是不是,太天真了

如果我们在schma中预设 name 这个字段的模式修饰符 trimtrue的话,在写入数据库的时候,会自动过滤掉这条数据前后的空格

name:{
	type:String,
	trim:true,
}

输入的数据:(空格)小张同学(空格)(空格)(空格)
实际写入数据库的数据:小张同学
lowercase、uppercase修饰符

同样的,预设 name 这个字段的模式修饰符 lowercase 或者 uppercasetrue的话,会将数据转化为小写或者大写

name:{
	type:String,
	lowercase:true,
}

输入的数据:ABbaYy
实际写入数据库的数据:abbayy

name:{
	type:String,
	uppercase:true,
}

输入的数据:ABbaYy
实际写入数据库的数据:ABBAYY
required修饰符

required : 表示这个数据必须传入

name:{
	type:String,
	required:true,
}
//不传入这个字段的数据,无法保存这条数据到数据库中,不信你试试
default修饰符

我们不妨来看一下default的中文含义:默认; 系统设定值; 预置值

你不难理解,default实际上就是在添加默认值,任何值或函数和函数都可以通过default设置,如果是函数,函数返回值为默认值

我们知道,在MongoDB中,如果按照原来的写法,没有Mongoose 预定义模式修饰符的话,我们针对这个字段不写入数据,实际在数据库对于这个字段是不会有数据的,但是我们如果在字段里预设default一个值,如果我们不写入这个字段的话,数据库会自动把我们的默认值写入这个字段

name:{
	type:String,
}
age:{
	type:Number,
	default:100
}
输入的数据:  name:小张同学
实际写入数据库的数据:  name:小张同学,age:100

比较常见的场景是这样的,我们发动态或者朋友圈的时候会发现有一个发布时间,这个是怎么实现的呢?
我们在schema的创建中预留一个CreateAtDate字段用来储存保存时间,每当我写入数据库的时候
就会默认把当前时间写入数据库

CreateAtDate: {    //用户创建时间 
			type:Date,
			default: Date.now()  //javascript中的内置函数,不要和我说你不会用
	}


用于验证String类型数据的修饰符

match修饰符

用法 match: 正则表达式

创建验证器,检查这个值是否匹配给定正则表达式(一般数据的验证给前端的同学做了,不过二重验证也是可以的嘛)

age:{
	type:Number,
	default:100,
	match:/\d+/
}

/\d+/表示必须是数字

enum修饰符

用法 enum:[ 你给定的数组]

创建验证器检查这个值是否包含于给定数组(你写入的值必须是我给定的数组里的,不然无法写入数据库)

language: {
        type: String,
        enum: ['Chinese', 'English']
      } //写入的值必须是数组中两个元素之一

maxlength,minlength修饰符

用法 maxlength:数字

​ minlength:数字

限制字符串的长度,比如说密码是12位到16位

password: {
        type: String,
         maxlength:16
		 minlength:12
      } 

小结:验证string类型的字段的数据,有match,enum,maxlength, minlength四种常见方法,这四个方法是可以叠加使用的

Number数据类型的验证修饰符

min: 数值 创建验证器检查属性是否大于或等于该值
max: 数值 创建验证器检查属性是否小于或等于该值

age:{
	type:Number,
	max:200,     //没见过这么大岁数的
	min:1         //1岁就会注册帐号了,小朋友有点东西
}

有关索引的修饰符

index: 布尔值 是否对这个属性创建索引
unique: 布尔值 是否对这个属性创建唯一索引
sparse: 布尔值 是否对这个属性创建稀疏索引

name:{
	type:String,
	index:true,
}

name:{
	type:String,
	unique:true,
}

Get与 Set修饰符(自定义)

​ 除了 mongoose 内置的修饰符以外,我们还可以通过 set(建议使用) 修饰符在增加数据的时候对数据进行格式化。也可以通过 get(不建议使用)在实例获取数据的时候对数据进行格式化

用法

set(params){ 
	//增加数据的时候对name这个字段进行处理
	//params用来获取你输入的值,对params处理以后,返回的数据就是在数据库中保存的数据
	}

我们举个栗子

这里我们插播一个广告!呸,插播一个知识点
Search()方法返回第一次出现的位置,不存在返回-1
var str='abcdef';
str.search('u'); //-1(表示不存在)
str.search('b'); //1


name:{
	type:String,
	set(params){ 
		if(!params){
			params =  ""; //如果是params没有传入数据,我们进行判断,返回一个空字符串保存到数据库
		}else{
		
		if(params.search("云顶书院的")!== -1){   // 判断有没有包含”云顶书院“这个字符串
			params = "云顶书院" + params; //没有给它加上
		}
		
		return params;
	}
}

//输入的数据:小张同学
//实际写入数据库的数据:云顶书院的小张同学

我们来看一下再来看一下get修饰符

name:{
	type:String,
	get(params){ params用来获取数据库中的值,对params处理以后,返回数据
		return "JS方向的" + params
	}
}

//这个实例的数据:小张同学
//实际输出的数据:JS方向的小张同学

实际这个get修饰符极其难用

我们使用mongoose的查询函数,查询出来的结果其实还是数据库中本身的样子,没有对name字段进行修饰

比如数据库中有这么条数据  {name:小张同学,age:100}
使用find函数查询后得到的结果会是   {name:小张同学,age:100}
这是怎么肥事,你不是输出结果的时候会修饰这个字段的数据吗?

其实是我们的打开方式不对
var user = new userModel({   //实例化一条数据,这一个实例数据甚至都没有保存到数据库
	name:小张同学,
	age:100
});   

我们这个时候打印出来name字段
console.log(user.name);    //输出的结果是:JS方向的小张同学

功能极其难用,谁设计的?建议拖出来枪毙五分钟

复杂条件查询(Query Selectors)

在使用针对于Model的查找方法时,可以对查询的字段有一些限制,我们来看一下常见的几个

比较查询运算符(Comparison)

比较查询运算符含义
$eq等于 :匹配等于指定值的值
$gt大于: 匹配大于指定值的值
$gte大于等于: 匹配大于或等于指定值的值
$in匹配数组中指定的任何值
$lt小于 :匹配小于指定值的值
$lte小于等于 :匹配小于或等于指定值的值
$ne匹配不等于指定值的所有值
$nin匹配数组中指定的任何值

我们来看几个实例(很简单哒)

userModel.find({age: {$lt: 100} }, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

//查询“age”中小于100的数据

userModel.find({name:  {$in: ["Lebron", "kuzma", "Davis"] } }, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

//查询“name”为"Lebron", "kuzma", "Davis"的三个人

逻辑查询运算符(Logical)

就像我们在编程语言中学习的一样,或且非三种

逻辑查询运算符含义
$and 将返回与两个查询条件匹配的所有文档
$not奇怪的非 反转查询表达式的效果,并返回与查询表达式不匹配的文档
$nor 将返回无法匹配这两个子句的所有文档
$or 将返回与任一查询条件匹配的所有文档
写法一:userModel.find({ $and: [
    {age: {$gte: 20}}, 
    {age: {$lt: 40}}
]}, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

//查询age字段值大于等于20到小于40的数据



userModel.find({ $nor: [
    {age: 30}, 
    {age: 50}
]}, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

查询age字段值不等于20和不等于40的数据

元素查询运算符(Element)

就是在查询数据是否存在这么一个字段,把存在这个字段的数据全查出来

元素查询运算符含义
$exists查询的字段值是否存在 : 匹配具有指定字段的文档
userModel.find({name:{$exists: true} }, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

//查询存在“name”字段的数据

常用的运算符

评估查询运算符

评估查询运算符含义
$mod与数据进行取模运算筛选
$regex使用正则表达式查询数据
$where支持js表达式查询
$mod:

userModel.find({ age: {$mod: [12, 0]}}, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

查找age字段中,数值与4取余后,值为0的数据

$regex:

userModel.find({ name: { $regex: "L+","$options":"i"}}, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

搜索以“L”开头的"name",“options”中的“i”代表不区分大小写(你要是学过正则就好理解了)

$where:

userModel.find({ $where: 'this.comments.length === 10 || this.name.length === 5' }, 
function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

数组查询运算符

针对数组字段的一些查询操作

数组查询运算符含义
$all(查询数组的本身及超集)匹配包含查询中指定的所有元素的数组
$elemMatch(查询数组的交集)如果数组字段中的元素与所有指定的$elemMatch条件匹配
$size(查询指定大小的数组)如果数组字段具有指定大小,请选择文档
$all:
tags: ['nodejs', 'mongoose']
userModel.find({ array: {$all:['Lebron', 'james']} } , 
function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});

查询“array”的字段值同时包含有['Lebron', 'james']的数据。只要值中包含此数组即返回数据,若是只包含数组中的一个则不返回此数据。

$elemMatch: 

userModel.find({ $elemMatch: { array: 'mongoose', age: 30} }, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});
查询“array”为“mongoose”或是“age”为“30”的数据

$size:

userModel.find(array: { $size: 2}, function(err, docs){
    if(err){
        console.log(err);
    }
    console.log('查到了:' + docs);
});
查询“array”数组中包含两个元素的数据
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值