mongodb学习笔记系列一

一、简介和安装
    ./bin/mongod --dbpath /path/to/database --logpath /path/to/log --fork --port 27017
    mongodb非常的占磁盘空间, 刚启动后要占3-4G左右,--smallfiles
二、基本命令
    1、登录mongodb client
        /use/local/mongo
    2、查看当前数据库
        show databases;
        show dbs;
        两个可能
    3、admin是和管理有关的库,local 是放schema有关的内容,不要乱动
    4、切换到数据库
        use admin;
        show tables;
        或者
        show collections;
            admin下的表不要随便操作。
    5、db help查看数据库操作帮助命令
    6、创建数据库:mongo是隐式创建
        use shop;
    7、创建表[集合]
        db.createcollection('user');
    8、show dbs;
    9、查看表[集合]
        show collections
    10、插入数据
        db.user.insert({name:lisi,age:22});
    11、查看数据:db.user.find();
    12、db.user.insert(id:3,name:'hmm',hoby:['basketball','fottball'],intro:{title:'my intro'});
    13、collection也是不用显示创建的
    14、db.goods.insert(_id:1,name:'n1',price:133);
        由此可见不用显示创建collection
    15、删除collection
        db.user.drop();//删除集合user
    16、db.dropDatabase();//删除database;
三、CRUD操作
    1、增加单篇文档
        db.stu.insert({sn:001,name,'xiaoming'});
        覆盖默认ID
        db.stu.insert({_id:002,sn:002,name:'lisi'});
    2、批量插入
        db.stu.insert({_id:3,sn:003,name:guangyu},{_id:4,sn:004,name:zhangwei});
    3、插入无限制深度的文档
        db.stu.insert({name:x:'li',m:'shimin'},{jli:'xxx'})
    4、删除
        db.stu.remove({sn:001});
        删除sn为001的文档
    5、删除全部
        db.stu.remove();
    6、查询表达式是json对象
    7、继续删除
        db.stu.remove(gender:'m');
        db.stu.remove(gender:'m',true);
        true限制只能删除一行
        
    8、错误的修改
        db.stu.update({name:'zhangsan'},{name:'lisi'});
        前一个表达式为想要修改的操作,后一个表达式表示要改成什么样。这个修改有问题,新文档直接替换旧文档,其他属性都不见了。
    9、正确的修改
        db.stu.update({name:'poxi'},{$set:{name:'yanpoxi'}});
        $set 修改
        $unset 重设 1-->true 0-->false
        $rename    重命名
        $inc 增长
        

        
        db.stu.update(
            {name:'wukong'},
            {
             $set:{name:'douzhanshengfo'},
             $unset:{jinggu:1},
             $rename:{set:gender},
             $inc:{age:2}
            }
            );
        
    
    10、multi 修改多行
            db.stu.update({
            {gender:'m'},
            {gender:'male'},
            {multi:1}
            })
    multiple表示可修改多行,不加只能修改匹配多行中的一行
    11、upsert $setonInsert
        db.stu.update(
            {name:'wuyong'},
            {$set:{name:'junshiwuyong'}}
            );
        如果没有wuyong这个人,那么将不做任何修改
        db.stu.update(
            {name:'wuyong'},
            {$set:{name:'junshiwuyong'}},
            {upsert:true}
            );
        如果添加upsert为true,那么自动插入
        但是这还是有问题,原来的字段会丢失
        这个时候需要upsert的setOnInsert
            db.stu.update(
            {name:'wuyong'},
            {$set:{name:'junshiwuyong'}},
            {upsert:true},
            {$setOnInsert:{gender:'male'}}//加上原来的字段
            );
    12、查询
        查询所有文档所有内容
        db.stu.find();
        查询所有文档的gender属性
        db.stu.find({},{gender:1})
        查询所有文档的gender属性,且不查询_id属性
        db.stu.find({},{gender:1,_id:0})

四:深入查询表达式
        1: 最简单的查询表达式
        {filed:value} ,是指查询field列的值为value的文档

        2: $ne --- != 查询表达式
        {field:{$nq:value}}
        作用--查filed列的值 不等于 value 的文档
           $gt--大于
               $lt--小于
           $lte小于等于
             $gte大于等于
        3: $nin --> not in
            {
                $nin
                [{cat_id:{$ne:30}},
                {cat_id:{$eq:300}}
                ]
            }

        4: $all
        语法: {field:{$all:[v1,v2..]}}
        是指取出 field列是一个数组,且至少包含 v1,v2值

        5、$or $and
            {
                $and:
                [{shop_price:{$gte:30}},
                {shop_price:{$lte:300}}
                ]
            }
            {
                $or
                [{shop_price:{$ne:30}},
                {shop_price:{$eq:300}}
                ]
            }
        6: $nor,
        {$nor,[条件1,条件2]}
        是指  所有条件都不满足的文档为真返回
        7、取模 $mod
            {
                goods_id:{$mode:[5,0]},
                
            },
            {
                goods_id:1,
                goods_name:1,
                _id:0
            }
        8、$exists 存在某一列则查出来
            {
                age:{$exists:1}
            },
            {
                goods_id:1,
                goods_name:1,
                _id:0
            }
        9、$type 按类型查询
            {
                age:{$type:2}
            }
          10、$where
            例: db.goods.find            ({$where:'this.cat_id != 3 && this.cat_id != 11'});
            直接将二进制数据转换为对象,对象的任何属性都可以导航得到、效率极低。不建议使用,好处是表达式可以写得很复杂和灵活
        11、用正则表达式查询 以”诺基亚”开头的商品
            例:db.goods.find({goods_name:/诺基亚.*/},{goods_name:1});
四、游标操作
        > var mycursor = db.bar.find({_id:{$lte:5}})
        > while(mycursor.hasNext()) {
        ... printjson(mycursor.next());
        ... }
五、用户管理
六、导入导出
七、副本集
    如果主服务器自动关掉
        rs.shutdownServer();
    会自动切换到别的服务器作为主服务器
    编写mongo副本集的自动化安装脚本:参考mongo副本集安装脚本.sh
八、分片
    分片配置
    1、启动两台mongo服务器
        mkdir -p /home/m17 /home/m18 /home/m20 /home/m30 /home/mlog
        mongd --dbpath /home/m17 --logpath /home/mlog/m17.log --fork --port 27017
        mongd --dbpath /home/m18 --logpath /home/mlog/m18.log --fork --port 27018
    2、配置configserver,管理meta信息
        mongd --dbpath /home/m20 --logpath /home/mlog/m20.log --fork --port 27020  --configserver
    3、配置一台mongo路由
        mongos --logpath /home/mlog/m30.log  --port 30000 --configdb 192.168.1.202:27020 --fork
    4、连接路由
        mongo --port 30000
    5、在路由节点增加片节点
        sh.addShard('192.168.10.202:27017')
        sh.addShard('192.168.10.202:27018')
    
    6、在路由节点查看路由状态,发现路由片节点信息
        sh.status();
    7、在路由节点插入数据
    8、路由节点有数据,发现17有数据,18没有数据。因为没有加入路由规则的原因
    9、sh.status 可以看到数据库,分区false,优先被放在shard0000
    10、针对数据库启用分片
        sh.enableShard('shard');
    11、sh.status 可以看到数据库shop,分区false,优先被放在shard0000
    12、添加分片的表
        sh.shardCollection(‘shop.goods’,{good_id:1});
        将good_id作为片键
    13、查看sh.status,可以看到现实目前分片信息先落在shard0001
    14、插入3W条数据
    15、查看sh.status ,看到数据都落在shard0001上
    16、再插入10W条数据,看到数据还是都落在shard0001上
    17、上面疑问的原因如下:
        
        mongodb不是从单篇文档的级别,绝对平均的散落在各个片上,

        而是N篇文档,形成一个块"chunk",
        优先放在某个片上,
        当这片上的chunk,比另一个片的chunk,区别比较大时, (>=3) ,会把本片上的chunk,移到另一个片上, 以chunk为单位,
        维护片之间的数据均衡

        问: 为什么插入了10万条数据,才2个chunk?
        答: 说明chunk比较大(默认是64M)
        在config数据库中,修改chunksize的值.

        问: 既然优先往某个片上插入,当chunk失衡时,再移动chunk,
        自然,随着数据的增多,shard的实例之间,有chunk来回移动的现象,这将带来什么问题?
        答: 服务器之间IO的增加,

        接上问: 能否我定义一个规则, 某N条数据形成1个块,预告分配M个chunk,
        M个chunk预告分配在不同片上.
        以后的数据直接入各自预分配好的chunk,不再来回移动?

        答: 能, 手动预先分片!
    18、在config数据库,修改chunk
        use config;
        show tables;
        db.settings.find();
        db.settings.save({_id:chunksize},{$set:{value:1}})
    19、查看分片信息
        sh.status();
    20、继续插入更多数据15W吧 50W也可以的
    21、查看分片信息
        sh.status();
    22、可以看到两台片节点的分片数量大致平衡


    手动预先分片:
        1、对shop库下的user表分片,片键为userid
        sh.shardingCollection('shop.user',{userid:1})
        2、sh.status();
        3、模拟:40个块每个块1000条数据
        4、定义规则
            for(var i = 1;i<=40;i++){
                sh.splitAt('shop.user',{userid:i*1000});        

            }
            这样将会有40个chunk,这些chunk会平均分布到各节点上,这样插入的时候就不会产生chunk频繁移动的现象了
        5、快速查看分片信息
            sh.status();
        6、插入4W条数据
            for(var i = 0;i<40000;i++){
                db.user.insert({userid:i,name:'nnnn hello'});
            }
        7、查看两个分片节点的总数据,各2W条数据
九、分片和副本集配合
    B--configserver
    C--副本集
    D--副本集
        1、分别创建副本集C、D,利用脚本自动化创建
        2、副本集C,D可以认为是一台机器,将分片节点设置到C、D的主节点即可
        3、配置configserver,管理meta信息
        mongd --dbpath /home/m20 --logpath /home/mlog/m20.log --fork --port 27020  --configsvr
        4、配置一台mongo路由
        mongos --logpath /home/mlog/m30.log  --port 30000 --configdb 192.168.1.202:27020 --fork
            
        5、在路由节点增加片节点
        sh.addShard('rs3/192.168.10.203:27017')#假设203的27017就是C的主节点
        sh.addShard('rs4/192.168.10.203:27018')#假设203的27017就是D的主节点
        6、添加需要分片的库
            sh.enableSharding('shop');
        7、添加需要分片的表
            sh.shardCollection('shop.user',{userid:1});
        8、手动分片测试
            sh.splitAt('shop.user',{userid:1000})#1千条数据拆分一下
            sh.splitAt('shop.user',{userid:2000})#两千条数据后拆分一下
            sh.splitAt('shop.user',{userid:3000})#3千条数据后拆分一下

        9、插入数据
            for(var i = 0;i<4000;i++){
                        
                    db.user.insert({    userid:i,intro:'i am lili'});

            }    
        10、查看两个副本集的数据量
            包括主节点和从节点
        11、移除某个分片
            use admin
            db.runCommand({removeShard:"rs2"})
        12、查询分片上的信息
            sh.status();
            可以看到被移除分片的数据移动到别的分片上
            并且被移除分片被标记上"draining" : true
        13、将移除的分片恢复
            db.shards.update({"_id" : "rs2"},{$unset:{draining:true}}, false, true)
            可以看到分片的数据移动到恢复的分片的上
        14、
十、网址转换项目
    1、功能说明
        *输入网址
        *点击变短
        *生成比较短的网址
        *如果已经存在短网址,提示已经存在
        *需要存储数据
            原网址        短网址
    2、短网址生成
    3、PHP连接mongodb编译扩展
        
        
    
        
                

 

posted @ 2014-06-27 13:35  在路上.......  阅读(282)  评论(0编辑  收藏  举报