NoSQL学习笔记(七)文档查询,复杂查询,管道查询,索引


文档查询/嵌套子文档

创建数据:
为db.students表的zzxb添加新的字段:学习经历字段

db.students.updateOne(
    {
        stuname:'zzxb'
    },
    {
        $set:{
            schools:[
                {school:'善邻路小学',score:'A'},
                {school:'140中学',score:'B'},
        {school:'109高中',score:'A+'}
            ]
        }
    }
)

点语法

eg1:查询在109中学上学的学生信息

db.students.find(
    {
        'schools.school':'109高中'
    }
)

注意点语法要用引号括起来

eg2:查询在109中学上学,且成绩为A+的学生的信息
法一(错误做法)

db.students.find(
    {
        'schools.school':'109高中',
        'schools.score':'A+'
    }
)

这样写是错的,虽然最后能把zzxb的信息查出来,但“109高中”和“A+”匹配的并不一定是同一个嵌套子文档。
如果把等级“A+”改成“B”,会发现一样能查出来。

法二:使用$elemMatch

db.students.find(
    {
        schools:{
            $elemMatch : {
                school:'109高中',
                score:'A+'
            }
        }
    }
)

复杂查询

where查询

eg1:查询年龄大于25岁的学生信息(学生表students在db库里)
用查询器的写法:

db.students.find(
    
)

法一:使用字符串

db.students.find(
    {
        $where:'this.age>25'
    }
)

法二:使用完整JS函数形式
eg1:查询年龄大于25岁且小于36岁的学生信息

db.students.find(
    {
        $where:function(){
            if(this.age>25&&this.age<36){
                return this;
            }
        }
    }
)

查询书本数量大于3本书的学生信息(数组长度)

db.students.find(
    {
        $where:function(){
            if(this.books.length>3){
                return this;
            }
        }
    }
)

查询拥有oracle书,且所在城市是济南的学生信息:
用查询器的写法:

db.students.find(
    {
        city:'jinan',
        books:{
            $all:['oracle']
        }
    }
)

用js的写法:

db.students.find(
    {
        $where:function(){
            if(this.city=='jinan'){
                for(var i = 0;i<this.books.length;i++){
                    if(this.books[i]=='oracle'){
                        return this;
                    }
                }
            }
        }
    }
)

limit

分页查询
eg: 查询出前五条记录的学生信息

db.students2.find(
    {},
    {
        _id:0,
        stuname:1
    }
    ).limit(5)

skip

db.students2.find({}).limit(5).skip(5);

eg:分页显示,每页显示3条记录:

db.students.find({}).limit(3).skip(0)
db.students.find({}).limit(3).skip(3)
db.students.find({}).limit(3).skip(6)
db.students.find({}).limit(3).skip(9)

sort排序

1:升序,-1:降序,允许多条件排序

eg:查询所出有学生记录,按年龄升序

db.students2.find().sort({
    age:1
})

eg:查询所出有学生记录,按年龄升序,年龄相同的按hadoop成绩降序

db.students2.find().sort({
    age:1,
    hadoop:-1
})

管道查询

$group

查询出学生表的学生数;

db.students.aggregate(
    [
        {
            $group : {
                _id: null,
                total:{
                    $sum:1
                }
            }
        }
    ]
)

查询出各个城市有多少学生:

db.students.aggregate(
    [
        {
            $group:{
                _id:'$city',
                total:{
                    $sum:1
                }
            }
        }
    ]


)
  • _id必须required,但它值可以为null
  • total是可以自定义的名称,用于显示结果字段值
  • $sum表示累计,统计数量时其值为1

eg2:查询出各个城市有多少学生,并排序(升序)

db.students.aggregate(
    [
        {
            $group:{
                _id:'$city',
                total:{
                    $sum:1
                }
            }
        },
        {
            $sort:{
                total:1
            }
        }
        
    ]
)

$match

db.students.aggregate(
    [
        {
            $group:{
                _id:'$city',
                total:{
                    $sum:1
                }
            }
        },
        {
            $match:{
                total:{
                    $gt:2
                }
            }
        },
        {
            $sort:{
                total:1
            }
        }        
    ]
)

常用的数值管道函数

如sum,avg,min
eg:查询所有学生java的总成绩

db.students.aggregate(
    [
        {
            $group:{
                _id:null,
                java_sum:{
                    $sum:'$java'
                }
            }
        }
    ]
)

eg:查询所有学生java的平均成绩

db.students.aggregate(
    [
        {
            $group:{
                _id:null,
                java_sum:{
                    $avg:'$java'
                }
            }
        }
    ]
)

eg:查询所有学生的各科平均成绩

db.students.aggregate(
    [
        {
            $group:{
                _id:null,
                java_sum:{
                    $avg:'$java'
                },
                hadoop_sum:{
                    $avg:'$hadoop'
                },
                hive_sum:{
                    $avg:'$hive'
                },
            }
        }
    ]
)

$project

$project用于控制显示哪些字段

一些运算函数,如$add$subtract$multiply$divide,只能在project下使用。

eg:查询所有学生各科的总成绩,并升序排序

db.students.aggregate(
    [
        {
            $project:{
                _id:0,
                stuname:1,
                total:{
                    $add:['$java','$hadoop','$hive']
                }
            }
        },
        {
            $sort:{
                total:1
            }
        }
    ]
)

可以看到查询结果有一行的结果为null:



因为有一个同学的hive成绩为null,因此其总成绩也为null

$ifNull

$ifNull用于将null字段转化为指定值。
用法:

$ifNull:[指定字段, 指定值]

上面的例题:查询所有学生各科的总成绩,并升序排序

db.students.aggregate(
    [
        {
            $project:{
                _id:0,
                stuname:1,
                total:{
                    $add:
                        [
                            '$java',
                            '$hadoop',
                            {
                                $ifNull:['$hive',0]
                            }
                        ]
                }
            }
        },
        {
            $sort:{
                total:1
            }
        }
    ]
)

索引

见老师上课的笔记

声明:奋斗小刘|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - NoSQL学习笔记(七)文档查询,复杂查询,管道查询,索引


Make Everyday Count