Mongoose之查询篇

7,590 阅读3分钟

前言

小女子最近开始转战服务端,由于才疏学浅,每每操作数据库,都要查阅文档,今日,得空,小女子呕心沥血地整理出此文章,希望给跟我一样的菜鸟有所帮助。

操作数据库,说到底就是增、删、改、查。今天的文章,从用的最多地查询开始吧。

查询

查询方法

mongoose查询使用的最基础的方法就是find、findOne和findById等方法,find查询所有满足条件的值并且返回一个数组,findOne和findById取满足条件的某一个值,返回的是一个object。

Model.find(conditions, [fields], [options], [callback])

注:conditions 查询条件、fields 想要返回的字段、options 、callback 回调函数

栗子: 查询用户表下面名字为张三的从第二条开始的后两条文档且只需按时姓名、性别、居住地址、创建时间信息并按创建时间倒叙显示

//对象写法
userModel.find({'name':'张三'},{'name':1,'sex':1,'region':1,'createBy':1,'_id':0},{ limit:2, skip:1, sort:'-createBy.createTime'})

//链式写法
userModel.find({'name':'张三'},{'name':1,'sex':1,'region':1,'createBy':1,'_id':0}).skip(7).limit(2).sort({'createBy.createTime' : -1})

常见的查询条件

mongoose查询条件其实就是在find或findOne方法的基础上添加mongodb条件操作符

常见的mongodb条件操作符有很多,如下:

    $or    或关系

  $nor    或关系取反

  $gt    大于

  $gte    大于等于

  $lt     小于

  $lte     小于等于

  $ne            不等于

  $in             在多个值范围内

  $nin           不在多个值范围内

  $all            匹配数组中多个值

  $regex  正则,用于模糊查询

  $size   匹配数组大小

  $maxDistance  范围查询,距离(基于LBS)

  $mod     取模运算

  $near   邻域查询,查询附近的位置(基于LBS)

  $exists    字段是否存在

  $elemMatch  匹配内数组内的元素

  $within  范围查询(基于LBS)

  $box    范围查询,矩形范围(基于LBS)

  $center       范围醒询,圆形范围(基于LBS)

  $centerSphere  范围查询,球形范围(基于LBS)

  $slice    查询字段集合中的元素(比如从第几个之后,第N到第M个元素)

字段的显示与隐藏

在 mongoose 中有两种指定方式,字符串指定和对象形式指定。

1.字符串指定时在排除的字段前加 - 号,只写字段名的是包含。

Model.find({},'age');
Model.find({},'-name');

2.对象形式指定时,1 是包含,0 是排除。

Model.find({}, { age: 1 });
Model.find({}, { name: 0 });

分页查询

  1. sort:按照排序规则根据所给的字段进行排序,值可以是 asc, desc, ascending, descending, 1, 和 -1。
  2. limit:指定返回结果的最大数量。
  3. skip:指定要跳过的文档数量
  4. lean:返回普通的 js 对象,而不是 Mongoose Documents。建议不需要 mongoose 特殊处理就返给前端的数据都最好使用该方法转成普通 js 对象。 注:sort 和 limit 同时使用时,调用的顺序并不重要,返回的数据都是先排序后限制数量。
Model.find(conditions).skip(pageTotal * pageNum).limit(pageTotal).sort({'_id':-1}).exec(cb);

pageTotal为每页显示条数、pageNum为分页数量、cb为回调函数,sort({'_id':-1})为按照_id倒叙排列

查询非空字段

Model.find(conditions:{$exists:true})
Model.find(conditions:{$ne:null})

数组对象的查找

数据

{author: [{name: "dora", age: 18 },{name: "wang", age: 16 }]}

1.精确查询

Model.find({ author: { name: "dora", age: 18 } })

2.点语法查询

Model.find({ 'author.age': { $gte: 18 } })

3.$elemMatch 同时满足所有查询条件

Model.find({ "author": {$elemMatch: {name: 'dora', age:{ $lt: 18 }}})
// []

数组的下标查询

数据

{ year: [ 2018, 2019 ] }
{ year: [ 2017, 2019, 2020 ] }
{ year: [ 2016, 2020 ] }

数组 year 的第二个值大于2019。

Model.find({ 'year.1': { $gt: 2019 } })
// { "_id" : ..., "year" : [ 2016, 2020 ] }

嵌套对象字段的查找

数据

{
  name: { first: "dora", last: "wang" }
}

1.精确匹配,顺序、字段都必须一致。

Model.find({ name: { last: "wang", first: "dora" } })
// [] 找不到数据

2.使用点语法,可匹配嵌套的字段,其中字段名必须用引号引起来。

Model.find({ 'name.last': 'wang' })

多表联合查询

mongoose其实没有多表联合查询的方法,不过我们可以通过多次查询来实现。 通过user的name、post的content查询post: schema.js

var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

var UserSchema = new Schema({
    name  : { type: String, unique: true },
    posts : [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});
var User = mongoose.model('User', UserSchema);

var PostSchema = new Schema({
    poster   : { type: Schema.Types.ObjectId, ref: 'User' },
    comments : [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
    title    : String,
    content  : String
});
var Post = mongoose.model('Post', PostSchema);
User.find({name: name}, function (err, users) {
    Post.find({poster: {$in: users}, content: content}, function (err, posts) {
        console.log(posts)
    })
})

总结

这些基本是我最近一周以来,经常查阅文档的内容,一边归档的同时也一边学习了下,一举两得了。但是整理完,感觉目录分的不够清晰,还是有点乱的,日后还需要改进,目前,我已经尽力了。谢谢观看