3.7 Mongoose基于Model的查询操作

使用Mongoose来查找文档很容易,有以下3种方法可供选择

find()
findById()
findOne()

find()

第一个参数表示查询条件,第二个参数用于控制返回的字段 selection,第三个参数用于配置查询参数,第四个参数是回调函数,回调函数的形式为function(err,docs){}

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

现在,使用find()方法找出所有数据

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);
        temp.find(function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },
            //{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]
            console.log(docs);
        })
    }
});

找出年龄大于18的数据

        temp.find({age:{$gte:18}},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]
            console.log(docs);
        })

找出年龄大于18且名字里存在'huo'的数据

        temp.find({name:/huo/,age:{$gte:18}},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]
            console.log(docs);
        })

找出名字里存在'a'的数据,且只输出'name'字段

[注意] :_id字段默认输出

        temp.find({name:/a/},'name',function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang' } ]
            console.log(docs);
        })

如果确实不需要_id字段输出,可以进行如下设置

        temp.find({name:/a/},{name:1,_id:0},function(err,docs){
            //[ { name: 'huochai' }, { name: 'wang' } ]
            console.log(docs);
        })

找出跳过前两条数据的其他所有数据

[注意]如果使用第三个参数,前两个参数如果没有值,需要设置为null

        temp.find(null,null,{skip:2},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },
            //{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]
            console.log(docs);
        })

findById()

Model.findById(id, [projection], [options], [callback])

显示第0个元素的所有字段

        var aIDArr = [];
        temp.find(function(err,docs){
            docs.forEach(function(item,index,arr){
                aIDArr.push(item._id);
            })
            temp.findById(aIDArr[0],function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
                console.log(doc);
            })            
        })

以上代码的另一种写法如下

        var aIDArr = [];
        temp.find(function(err,docs){
            docs.forEach(function(item,index,arr){
                aIDArr.push(item._id);
            })
            temp.findById(aIDArr[0]).exec(function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
                console.log(doc);
            })            
        })

只输出name字段

            temp.findById(aIDArr[0],{name:1,_id:0},function(err,doc){
                //{  name: 'huochai'}
                console.log(doc);
            })

或者写成下面这种形式

            temp.findById(aIDArr[0],{name:1,_id:0}).exec(function(err,doc){
                //{  name: 'huochai'}
                console.log(doc);
            })

输出最少的字段

            temp.findById(aIDArr[0],{lean:true},function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c }
                console.log(doc);
            })   
            temp.findById(aIDArr[0],{lean:true}).exec(function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c }
                console.log(doc);
            })

findOne()

该方法返回查找到的所有实例的第一个

Model.findOne([conditions], [projection], [options], [callback])

找出age>20的文档中的第一个文档

temp.findOne({age:{$gt : 20}},function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}}).exec(function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
    console.log(doc);
})

找出age>20的文档中的第一个文档,且只输出name字段

temp.findOne({age:{$gt : 20}},{name:1,_id:0},function(err,doc){
    //{ name: 'huochai' }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}},{name:1,_id:0}).exec(function(err,doc){
    //{ name: 'huochai' }
    console.log(doc);
})

找出age>20的文档中的第一个文档,且输出包含name字段在内的最短字段

temp.findOne({age:{$gt : 20}},"name",{lean:true},function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}},"name").lean().exec(function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }
    console.log(doc);
})

文档查询中,常用的查询条件如下

  • $gt 大于

  • $gte 大于等于

  • $lt 小于

  • $lte 小于等于

  • $ne 不等于

    this.ctx.model.Article.find({“sort”:{ $get:18 , $lte:30 });
  • $or 或关系

  • $nor 或关系取反

  • $in 在多个值范围内

  • $nin 不在多个值范围内

  • $all 匹配数组中多个值

    this.ctx.model.Article.find({"title":{ $in:[20,21,22."haha"]} );
    this.ctx.model.Article.find({"$or" :  [ {"age":18} , {"name":"wxw"} ] });
  • $regex 正则,用于模糊查询

    this.ctx.model.Article.find( {"name" : /joe/i } );
  • $size 匹配数组大小

    this.ctx.model.Article.find({"array":{$size : 3} }); //查询数组长度为三的
  • $maxDistance 范围查询,距离(基于LBS)

  • $mod 取模运算

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

  • $exists 字段是否存在

    this.ctx.model.Article.find({name: {$exists: true}},function(error,docs){
        console.log(doc) //存在
    });
    this.ctx.model.Article.find({telephone: {$exists: false}},function(error,docs){
        console.log(doc)//不存在
    });
  • $elemMatch 匹配内数组内的元素

  • $within 范围查询(基于LBS)

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

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

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

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

    this.ctx.model.Article.find({"array":{$slice : 10} }); // 获取匹配到数组的前10个元素
    this.ctx.model.Article.find({"array":{$slice :  [5,10]} }); // 获取匹配到数组的5-10个元素

$where

如果要进行更复杂的查询,需要使用$where操作符,$where操作符功能强大而且灵活,它可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数

使用字符串:

temp.find({$where:"this.x == this.y"},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}) 
temp.find({$where:"obj.x == obj.y"},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
})

使用函数

temp.find({$where:function(){
        return obj.x !== obj.y;
    }},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]
    console.log(docs);
})
temp.find({$where:function(){
        return this.x !== this.y;
    }},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]
    console.log(docs);
})

链式查询

在查询时候,不带回调,而查询条件通过API函数来制定,例如:

    var query = PersonModel.findOne({'name.last':'dragon'});
    query.select('some select');
    query.exec(function(err,pserson){
    //如果err==null,则person就能取到数据
  });

这种方式相对直接查询,分的比较明细,如果不带callback,则返回queryquery没有执行的预编译查询语句,该query对象执行的方法都将返回自己,只有在执行exec方法时才执行查询,而且必须有回调。

因为query的操作始终返回自身,我们可以采用更形象的链式写法

    Person
      .find({ occupation: /host/ })
      .where('name.last').equals('Ghost')
      .where('age').gt(17).lt(66)
      .where('likes').in(['vaporizing', 'talking'])
      .limit(10)
      .sort('-occupation')
      .select('name occupation')
      .hint({age:1,name:1,like:-1})    //是否启用稀疏索引  也就是如果这内部的没有值则跳过该值 1 标识需要 2标识不需要
      .exec(callback);

Last updated

Was this helpful?