美文网首页
Mac MongoDB学习(二)

Mac MongoDB学习(二)

作者: Kean_Qi | 来源:发表于2019-03-31 16:39 被阅读0次

    db.xxx.find使用

    在MySql,会对>大于),<(小于),=(等于)这些东西很熟悉,但是在db中会有区别,我们会用如下:
    小于($lt):英文全称less-than
    小于等于($lte):英文全称less-than-equal
    大于($gt):英文全称greater-than
    大于等于($gte):英文全称greater-than-equal
    不等于($ne):英文全称not-equal 我们现在要查找一下,公司内年龄小于30大于25岁的人员。
    _id不显示id

    db.workmate.find(
        {age: { $lte: 30, $gte: 25 }},
        {name:true, age:true, "skill.skillOne": true, _id: false}
        );
    

    日期查找
    MongoDB也提供了方便的日期查找方法现在我们要查找注册日期大于2018年1月10日的数据

    var startDate = new Date('01/01/2018');
    db.workmate.find(
        {regeditTime: {$gt: startDate}},
        {name:true, age:true, "skill.skillOne": false}
        );
    
    //查找age < 20
    db.workmate.find( {age: {$lt: 20}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    //查找age <= 20
    db.workmate.find( {age: {$lte: 20}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    //查找age == 20
    db.workmate.find( {age: 20}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    //查找age > 20
    db.workmate.find( {age: {$gt: 20}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    //查找age >= 20
    db.workmate.find( {age: {$gte: 20}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    

    find的多条件查询

    很多时候我们需要查询的值不只是有一个简单的条件,比如我们现在要查询一下同事中是33岁和25岁的,还比如我们要查询同事中大于30岁并且会PHP技能的。MongoDB在这方面也支持的很好.

    $in修饰符
    in修饰符可以轻松解决一键多值的查询情况。
    $in相对的修饰符是$nin

    //$in修饰符   >=a  <=b  a<b
    //查找 age >=20 <=33的信息
    db.workmate.find( {age: {$in: [20,33]}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    //$nin修饰符  <a  >b  a<b
    db.workmate.find( {age: {$nin: [20,33]}}, {name:true, age:true, "skill.skillOne": true, _id:false} );
    

    $or修饰符
    用来查询多个键值的情况,就比如查询同事中大于30岁或者会做PHP的信息,主要区别是两个Key值。$in修饰符是一个Key值.

    //$or修饰符
    //查询多个键值的情况  表示
    db.workmate.find( 
        {$or: [
            {age: {$gt: 20}},
            {"skill.skillThree":"PHP"}
         ]}, 
        {name:true, age:true, "skill.skillThree": true, _id:false} 
        );
    

    $and修饰符
    用来查找几个key值都满足的情况,比如要查询同事中大于30岁并且会做PHP的信息,这时需要注意的是这两项必须全部满足。

    //$and修饰符
    //$and用来查找几个key值都满足的情况
    db.workmate.find( 
        {$and: [
            {age: {$gt: 30}},
            {"skill.skillThree":"PHP"}
         ]}, 
        {name:true, age:true, "skill.skillThree": true, _id:false} 
        );
    

    $not修饰符
    用来查询除条件之外的值,比如我们现在要查找除年龄大于20岁,小于30岁的人员信息。

    //$not修饰符
    //用来查询除条件之外的值
    //比如我们现在要查找除年龄大于20岁,小于30岁的人员信息
    db.workmate.find( 
        {age: {$not: {$lte:30, $gte:20}}}, 
        {name:true, age:true, "skill.skillOne": true, _id:false} 
        );
    

    find的数组查询

    当知道了一个人的爱好是’画画’,’聚会’,’看电影’,但我们不知道是谁,这时候我们就可以使用最简单的数组查询
    注意查询多匹配的话要去掉[]

    //查找一个人的爱好只有对应项目的人员信息  不常用
    db.workmate.find(
        {interest:['画画', '聚会', '看电影']},
        {name:1, interest:1, age:1, _id:0}
        );
    db.workmate.find(
        {interest:['写代码', '篮球']},
        {name:1, interest:1, age:1, _id:0}
        );
    //带 '[]' 查找一个人的爱好只有'看电影'
    db.workmate.find(
        {interest:['看电影']},
        {name:1, interest:1, age:1, _id:0}
        );
    //不带 '[]'  查找有‘看电影’爱好的人的信息
    db.workmate.find(
        {interest:'看电影'},
        {name:1, interest:1, age:1, _id:0}
        );
    

    $all-数组多项查询
    现在我们的条件升级了,要查询出喜欢看电影和看书的人员信息,也就是对数组中的对象进行查询,这时候要用到一个新的查询修饰符$all。

    //$all-数组多项查询
    //要查询出喜欢看电影和看书的人员信息
    db.workmate.find(
        {interest:{$all: ['写代码', '篮球']}},
        {name:1, interest:1, age:1, _id:0}
        );
    

    这时候找到了兴趣中既有看电影又有看书的人员。

    $in-数组的或者查询
    主要满足数组中的一项就可以被查出来
    比如现在要查询爱好中有看电影的或者看书的员工信息。

    db.workmate.find(
        {interest:{$in:["看电影","看书"]}},
        {name:1,interest:1,age:1,_id:0}
    )
    

    $all-数组多项查询
    要查询出喜欢看电影和看书的人员信息

    db.workmate.find(
        {interest:{$all: ['写代码', '篮球']}},
        {name:1, interest:1, age:1, _id:0}
        );
    

    $size-数组个数查询
    查找兴趣个数是五个的信息

    db.workmate.find(
        {interest:{$size: 5}},
        {name:1, interest:1, age:1, _id:0}
        );
    

    $slice-显示选项
    有时候我并不需要显示出数组中的所有值,而是只显示前两项

    db.workmate.find(
        {},
        {name:1, interest: {$slice:2}, age:1, _id:0}
        );
    

    我们想显示兴趣的最后一项,可以直接使用slice:-1,来进行查询。

    db.workmate.find(
        {},
        {name:1, interest: {$slice:-1}, age:1, _id:0}
        );
    

    find的参数使用方法

    find还有几个常用的参数,这些参数多用在分页和排序上。
    作一个最简单的分页,
    我们把同事集合(collections)进行分页,
    每页显示两个,
    并且按照年龄从小到大的顺序排列

    find参数:
    query:这个就是查询条件,MongoDB默认的第一个参数。
    fields:(返回内容)查询出来后显示的结果样式,可以用true和false控制是否显示。
    limit:返回的数量,后边跟数字,控制每次查询返回的结果数量。
    skip:跳过多少个显示,和limit结合可以实现分页。
    sort:排序方式,从小到大排序使用1,从大到小排序使用-1。
    
    db.workmate.find(
        {},
        {name:1, age:1, _id:0}
        ).limit(0).skip(2).sort({age:1});
    

    $where修饰符
    是一个非常强大的修饰符,但强大的背后也意味着有风险存在。
    它可以让我们在条件里使用javascript的方法来进行复杂查询。

    db.workmate.find(
        {$where:"this.age>25"},
        {name:1, age:1, _id:0}
        ).limit(0).skip(2).sort({age:1});
    

    find如何在js文本中使用

    hasNext循环结果
    想在文本中执行我们的find语句要用到游标和循环的操作,先看一下代码,代码中我已经对每一句进行了注释。

    var db = connect("company")  //进行链接对应的集合collections
    var result = db.workmate.find() //声明变量result,并把查询结果赋值给result
    //利用游标的hasNext()进行循环输出结果。
    while(result.hasNext()){
        printjson(result.next())  //用json格式打印结果
    }
    

    forEach循环
    利用hasNext循环结果,需要借助while的帮助,MongoDB也为我们提供了forEach循环,现在修改上边的代码,使用forEach循环来输出结果。

    var db = connect("company")  //进行链接对应的集合collections
    var result = db.workmate.find() //声明变量result,并把查询结果赋值给result
    //利用游标的hasNext()进行循环输出结果。
    result.forEach(function(result){
        printjson(result)
    })
    

    索引:构造百万级数据

    索引的性能提现必须要有大量数据才能看出来,你说你有10条20条数据,这是根本看不出来效果的,这节课就通过随机数的方法,创造出一个百万级数据的数据库出来
    制作随机数方法:
    制作随机用户名:

    //生成随机数
    function getRandomNum(min, max) {
        var range = max - min; //得到随机数区间
        var rand = Math.random(); //得到随机值
        return (min + Math.round(rand * range));
    }
    
    function getRandomUserName(min, max) {
        //构造生成时的字母库数组
        var tempStringArray =  "123456789qwertyuiopasdfghjklzxcvbnm".split("");
        var outPuttext = ""; //最后输出的变量
    
        for (var i = 1; i<getRandomNum(min, max); i++){
            outPuttext = outPuttext + tempStringArray[getRandomNum(0, tempStringArray.length)];
        }
        return outPuttext;
    }
    

    插入200万数据 这个过程可能2-3分钟,插入完成后,我们可以使用 db.randomInfo.stats() 这个命令查看数据中的数据条数。

    var db = connect("company")  //进行链接对应的集合collections
    db.randomInfo.drop();
    
    var tmpInfo = [];
    var startTime = new Date().getTime();
    for(var i = 0; i<2000000; i++){
        tmpInfo.push({
            userName:getRandomUserName(7, 16),
            regeditTime:new Date(),
            randNum0: getRandomNum(100000, 999999),
            randNum1: getRandomNum(100000, 999999),
            randNum2: getRandomNum(100000, 999999),
            randNum3: getRandomNum(100000, 999999),
            randNum4: getRandomNum(100000, 999999),
            randNum5: getRandomNum(100000, 999999),
            randNum6: getRandomNum(100000, 999999),
            randNum7: getRandomNum(100000, 999999),
            randNum8: getRandomNum(100000, 999999),
            randNum9: getRandomNum(100000, 999999),
        });
    }
    db.randomInfo.insert(tmpInfo);
    var endTime = new Date().getTime();
    var useTime = endTime - startTime;
    print("[demo]: ----- [startTime] " + startTime + 'ms')
    print("[demo]: ----- [endTime] " + endTime + 'ms')
    print("[demo]: ----- [useTime] " + useTime + 'ms')
    

    我们先制作一个普通查询,随便查找一个用户名,并计算出查询和打印的时间,因为有200万条数据,所以性能不会很高。

    var startTime = new Date().getTime();
    var db = connect("company")  //进行链接对应的集合collections
    var rs = db.randomInfo.find({userName: 'z3y4n5wjv', randNum0: 112042,});
    rs.forEach(function(rs){
        printjson(rs)
    });
    var endTime = new Date().getTime();
    var useTime = endTime - startTime;
    print("[demo]: ----- [startTime] " + startTime + 'ms')
    print("[demo]: ----- [endTime] " + endTime + 'ms')
    print("[demo]: ----- [useTime] " + useTime + 'ms')
    

    上边的代码就是一个普通的查询,只不过是记录了时间。在终端运行后,可以得到大概的运行时间是0.8秒左右(电脑性能不同,有所不同),第一次无缓存的运行时间大概是3.5秒左右。这个时间是没办法满足我们的日常查询的。
    建立索引
    试着为用户名(username)建立索引。建立索引只需要一句话就可以了。

    //将userName添加到索引
    db.randomInfo.ensureIndex({userName:1}) 
    //将randNum0添加到索引
    db.randomInfo.ensureIndex({randNum0:1}) 
    //删除username_1索引
    db.randomInfo.dropIndex('username_1') 
    //查看现有索引
    db.randomInfo.getIndexes() 
    

    这时候查询的时间缩短到了4ms左右,查询性能提升了大概200倍左右。

    复合索引

    索引中的小坑

    记得我刚学MongoDB时,学会了索引,我就到处想用,甚至几百条数据的集合(collections),我也自作聪明的用一下,但结果往往是画蛇添足,走了不少弯路。通过实际开发和性能对比,我自己总结了几条不用索引的情况(不一定对,但是自己的经验之谈)。

    • 数据不超万条时,不需要使用索引。性能的提升并不明显,而大大增加了内存和硬盘的消耗。
    • 查询数据超过表数据量30%时,不要使用索引字段查询。实际证明会比不使用索引更慢,因为它大量检索了索引表和我们原表。
    • 数字索引,要比字符串索引快的多,在百万级甚至千万级数据量面前,使用数字索引是个明确的选择。
    • 把你经常查询的数据做成一个内嵌数据(对象型的数据),然后集体进行索引。

    复合索引就是两条以上的索引
    上边已经把username字段建立了索引,我们现在把randNum0,这个字段也设置成索引。

    db.randomInfo.ensureIndex({randNum0:1})
    

    建立好后,我们再用查询索引状态命令进行查询。

    db.randomInfo.getIndexes()
    

    两个索引同时查询
    从性能上看并没有什么特殊的变化,查询时间还是在4ms左右

    db.randomInfo.find({username:'7xwb8y3',randNum0:565509});
    

    指定索引查询(hint)
    数字的索引要比字符串的索引快,这就需要一个方法来打破索引表的查询顺序,用我们自己指定的索引优先查询,这个方法就是hint().

    var  rs= db.randomInfo.find({username:'7xwb8y3',randNum0:565509}).hint({randNum0:1});
    

    删除索引
    当索引性能不佳或起不到作用时,我们需要删除索引,删除索引的命令是dropIndex().
    注意的是删除时填写的值,并不是我们的字段名称(key),而是我们索引查询表中的name值

    db.randomInfo.dropIndex('randNum0_1');//索引的唯一ID
    

    索引:全文索引

    有些时候需要在大篇幅的文章中搜索关键词,比如我写的文章每篇都在万字以上,这时候你想搜索关键字是非常不容易的,MongoDB为我们提供了全文索引。

    • 我们先建立一个集合(collections)-info
    db.info.insert({contextInfo:"I am a programmer, I love life, love family. Every day after work, I write a diary."})
    db.info.insert({contextInfo:"I am a programmer, I love PlayGame, love drink. Every day after work, I playGame and drink."}
    

    建立全文索引

    db.info.ensureIndex({contextInfo:'text'})
    

    全文索引查找 建立好了全文索引就可以查找了,查找时需要两个关键修饰符:

    • $text:表示要在全文索引中查东西。
    • $search:后边跟查找的内容。
    db.info.find({$text:{$search:"programmer"}})
    

    查找多个词

    db.info.find({$text:{$search:"programmer family diary drink"}})
    

    如果我们这时候希望不查找出来有drink这个单词的记录,我们可以使用“-”减号来取消。

    db .info.find({$text:{$search:"programmer family diary -drink"}})
    

    转义符:
    全文搜索中是支持转义符的,比如我们想搜索的是两个词(love PlayGame和drink),这时候需要使用\斜杠来转意。

    db.info.find({$text:{$search:"\"love PlayGame\" drink"}})
    

    管理:用户的创建、删除与修改

    首先要进入我们的admin库中,进入方法是直接使用use admin 就可以。进入后可以使用show collections来查看数据库中的集合。默认是只有一个集合的(system.version)。
    创建用户可以用db.createUser方法来完成,里边参数还是蛮多的,代码我写在下边,然后对每一项做出了解释。

    //进入我们的admin库
    use admin;
    
    //创建用户
    /*单独配置一个数据库的权限
    内置角色:
    
    数据库用户角色:read、readWrite;
    数据库管理角色:dbAdmin、dbOwner、userAdmin;
    集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManage;
    备份恢复角色:backup、restore;
    所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
    超级用户角色:root
    内部角色:__system
    * */
    db.createUser({
        user: "zhangsan",
        pwd: "123456",
        customData: {
            name :  'zhangsan',
            email : 'abc@163.com',
            age: 18
        },
        roles:[{
            role: 'readWrite',
            db: 'company'
        },
            'read'
        ],
    })
    

    查找用户信息
    直接可以使用查找的方法,查找用户信息。

    // 查找用户信息
    db.system.users.find()
    

    删除用户:
    删除用户也是非常简单,直接用remove就可以删除这个用户的信息和权限。

    db.system.users.remove({user:'zhangsan}')
    

    建权
    有时候我们要验证用户的用户名密码是否正确,就需要用到MongoDB提供的健全操作。也算是一种登录操作,不过MongoDB把这叫做建权。
    如果正确返回1,如果错误返回0。

    db.auth('zhangsan', '123456')
    

    启动建权
    重启MongoDB服务器,然后设置必须使用建权登录。

    mongod --auth
    

    登录
    如果在配置用户之后,用户想登录,可以使用mongo的形式,不过需要配置用户名密码,我们就可以用给我们的权限对数据库操作了

    mongo -u zhangsan -p 123456 127.0.0.1:27017/admin
    

    管理:备份和还原

    作为一个数据库管理员,对数据库的备份和还原是比作的两项工作。其实用起来是相当简单的,就是mongodumpmongorestore两个命令。
    备份
    比如现在我们备份所有MongoDB里的库的databack文件夹下,就可以把命令写成这样

    mongodump --host 127.0.0.1 --port 27017 --out D:/databack/
    

    数据恢复
    备份好后,如果数据库有意外或者遭受到了攻击,我们要进行回复数据库,这时候就可以使用mongorestore命令。

    mongorestore --host 127.0.0.1 --port 27017 D:/databack/
    

    相关文章

      网友评论

          本文标题:Mac MongoDB学习(二)

          本文链接:https://www.haomeiwen.com/subject/yrsybqtx.html