zoukankan      html  css  js  c++  java
  • MongoDB 学习笔记

    以下命令中若有 --fork 参数(表示后台运行),则只在linux下有用,在windows下需去掉此参数

    命令集:
    use foobar  切换到foobar数据库
    help 显示所有可用命令
    db.help() 显示数据库级别的命令
    db.foo.help() 显示集合级别的命令

    db  显示当前数据库


    db.blog.insert({"title":"My Blog"})

    db.blog.update({"title":"My Blog"}, {"title":"My first blog"})
    更新记录, 第一个参数是要更新记录的查询条件, 第二个参数是更新后的内容

    db.blog.find({}, {"author" : 1, "email": 1})
       第一个参数为查询条件,第二个参数为要返回的字段列表。


    修改器
    $inc 增加指定的键的值,如不存在则创建。
       e.g.  db.blog.update({"title":"My Blog"}, {"$inc": {"vote" : 10}})

    $set 更新指定的键的值,如不存在则创建。
       e.g.  db.blog.update({"title":"My Blog"}, {"$set": {"author" : "shj"}})

    $unset 移除一个键。e.g. db.blog.update({"title":"My Blog"}, {"$unset": {"author" : 1}})

    $push 向数组末尾加入一个元素,如不存在则创建数组。
        e.g. db.blog.update({"title":"My Blog"}, {"$push": {"comments": {"name":"joe", "comment" : "good"}}})

    $addToSet 数组里面若不存在对应的值,就加进去。
        e.g. db.users.update({"name":"shj"}, {"$addToSet": {"emails" : "123@163.com"}})
        emails数组里如果没有123@163.com, 则会补添加进去。

    $pop 从数组中删除一个元素。 只能删除头部或尾部元素。
        e.g. db.users.update({"name":"shj"},{"$pop": {"emails": 1}})
        其中1表示从数组末尾删除一个元素。-1 则是从头部删除一个。

    $pull 从数组中删除一个元素。
        e.g. db.lists.update({}, {"$pull": {"todo":"laundry"}}) 删除todo数组中的"laundry"

    save 保存一个文档。若存在则更新。
        e.g. db.blog.save({"title":"My Blog"})

    findAndModify 找到并修改。这是一个原子操作。
    db.runCommand({"findAndModify": "blog", // blog -- 集合名
                   "query":{"votes":0},     // query -- 查询条件
                   "sort":{"votes":-1},     // sore -- 排序条件
                   "update":{"$set", {"votes": 2}},
                   "new":true               // new -- 返回更新前的还是更新后的文档
                   //,"remove" : ture       // remove -- 删除query匹配的文档
                  })  // update -- 更新操作

    查询条件
    1. $lt, $lte, $gt, $gte
      db.users.find({"age":{"$gte": 18, "$lte" : 30}})

    2. $in, $nin
      db.users.find({"userid" : {"$in" : [12345, "joe"]}})

    3. $or
      db.users.find({"$or" : [{"userid" : 12345}, {"name" : "joe"}]})

    4. $not
      db.users.find({"userid" : {"$not" : {"name" : "joe"}}})

    5. null值,匹配自身和不存在该键的文档
       e.g. db.users.find({"birthday" : null}) 匹配birthday的值为null的文档和所有
       不存在birthday这个键的文档。可通过$exists 条件判断键是否存在。

    6. $exists
       e.g. db.users.find({"birthday" : {"$in" : [null], "$exists" : true}})

    7. $all 多个元素来匹配数组
       e.g. db.food.insert({"fruit" : ["apple", "banana", "peach"]})  
            db.food.insert({"fruit" : ["apple", "kumquat", "orange"]})
            db.food.insert({"fruit" : ["cherry", "banana", "apple"]})
            db.food.find({"fruit" : {$all : ["apple", "banana"]}}) -- 返回第1条和第3条

    8. $size 查询指定长度的数组
       e.g. db.food.find({"fruit" : {$size : 3}})

    9. $slice 返回数组的一个子集合
       e.g. db.blog.find({"title" : "my blog"}, {"comments" : {"$slice" : 10}}) -- 返回前10条comments
            db.blog.find({"title" : "my blog"}, {"comments" : {"$slice" : -10}}) -- 返回最后10条comments
            db.blog.find({"title" : "my blog"}, {"comments" : {"$slice" : [2, 10]}}) -- 忽略前面的2条,返回2条之后的10条comments

    10. $elemMatch 将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到。
        e.g.  db.blog.insert({"title" : "my blog",
                   "comments" : [
                                {"author" : "joe", "score" : 4, "comment": "nice"},
                                {"author" : "mary", "score" : 6, "comment": "terrible"}]})
        假设需要查找由joe发表的5分以上的评论,则:
        db.blog.find({"comments" : {"author" : "joe", "score" : {"$gte":5}}}) -- 不对,内嵌文档查询要求内嵌文档完全匹配
        db.blog.find({"comments.author" : "joe", "comments.score" : {"$gte":5}}) --不对,author和score是or的关系,不是要求的and
        db.blog.find({"comments" : {"$elemMatch": {"author" : "joe", "score" : {"$gte":5}}}}) -- 正确

    11. $near 用于查询附近的坐标、位置
       e.g.  db.map.find({"gps" : {"$near" : [40, -73]})

    12. $within 找到指定形状内的文档。
       e.g. db.map.find({"gps" : {"$within" : {"$box" : [[10, 20], [15,30]]}}})
       $box参数是两个元素的数组,第一个指定了左下角的坐标,第二个指定了右上角的坐标
       e.g. db.map.find({"gps" : {"$within" : {"$center" : [[10, 20], 5]}}})
       $center参数是两个元素的数组,第一个是圆心,第二个是半径
     
    13. $where
       e.g. db.blog.find({"$where" : function(){
               for(var current in this){
              for(var other in this){
                 if(current != other && this[current] == this[other]){
                return true;
             }
              }
           }
           return false;
            }})   
       返回true的文档将做为结果的一部分返回


    db.blog.find().limit(3) -- 限制返回的结果数为3
    db.blog.find().skip(3) -- 忽略前三个匹配文档
    db.blog.find().sort({name: 1 , age : -1}) -- name升序,age降序

    db.blog.ensureIndex({"username":1}, {"unique" : true}) -- 对username进行索引,并设置唯一
    db.blog.find().explain("executionStats")


    db.blog.count() -- 集合中的文档数量

    db.blog.drop() -- 删除一个集合

    db.listCommands() -- 列出所有命令

    db.createCollection({"my_collection", {capped: true, size: 10000}}) -- 创建固定集合,大小10000字节

    db.serverStatus() -- 查看实例运行状态
    db.stats() -- 查看数据库状态信息


    开启profiling(慢查询日志,用于记录执行时间较长的命令,以便于调优)
    (1) 在启动时设置 mongod -profile=级别
    (2) > db.setProfilingLevel(级别, slowms);
    说明:级别有三种: 0(不开启),1(记录慢命令,默认为 > 100ms),2(记录所有命令)
    开启后可以查询: >use admin
                    >db.system.profile.find()


    导出数据:
    mongoexport -d my_mongodb -c user -o e:user.dat
    说明: -d 要导出的数据库名
           -c 要导出的数据库表
           -o 存放导出文件的位置
    mongoexport -d my_mongodb -c user --type=csv -f uid,username,age -o e:user_csv.dat
    说明:导出CSV格式的文件,必须有 -f 参数,表示需要导出的列

    导入数据:
    mongoimport -d my_mongodb -c user e:user.dat
    mongoimport -d my_mongodb -c user --type csv --headerline --file e:user_csv.dat
    说明:--headerline 批明不导入第一行,因为第一行是列名


    数据备份:
    mongodump -d test  -o e:my_mongodb_dump

    数据恢复:
    mongorestore -d test e:my_mongodb_dump est


    访问控制
    1. 绑定 IP 内网地址访问 MongoDB 服务
       mongod --bind_ip 192.168.1.103     只允许192.168.1.103 访问 MongoDB 服务
    2. 设置监听端口
       mongod --bind_ip 192.168.1.103 --port 28018
    3. 使用用户名和口令登录
       启动:mongod --auth
       要先添加用户后方可用用户名登陆:
        > use admin   #1. 切换数据库
        >db.createUser(  
          {
            user: "dba",
            pwd: "dba",
            roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
          }
        )   #2. 创建用户,只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
        > db.auth('dba','dba')  #3. 认证用户
        > use test    #4. 切换数据库
        > db.createUser(  #5. 创建一个连接数据库的帐号
            {
              user: "zjyr",
              pwd: "zjyr",
              roles: [
                 { role: "read", db: "test" }    #只读帐号
              ]
            }
        )
       连接:mongo -u root -p


    MapReduce:
    准备的数据:
    > db.students.insert({classid:1, age:14, name:'Tom'})
    > db.students.insert({classid:1, age:12, name:'Jacky'})
    > db.students.insert({classid:2, age:16, name:'Lily'})
    > db.students.insert({classid:2, age:9, name:'Tony'})
    > db.students.insert({classid:2, age:19, name:'Harry'})
    > db.students.insert({classid:2, age:13, name:'Vincent'})
    > db.students.insert({classid:1, age:14, name:'Bill'})
    > db.students.insert({classid:2, age:17, name:'Bruce'})

    设置Map函数:Map 函数必须调用 emit(key, value) 返回键值对,使用 this 访问当前待处理的 Document
    > map = function() { emit(this.classid, 1) }
    设置reduce函数
    > reduce = function(key, values) {
        var x = 0;
        values.forEach(function(v) { x += v });
        return x;
      }
    进行处理:
    > res = db.runCommand({
        mapreduce:"students",
        map:map,
        reduce:reduce,
        out:"students_res"
      })
    查看结果:
    > db.students_res.find()

    利用 finalize() 我们可以对 reduce() 的结果做进一步处理:
    > f = function(key, value) { return {classid:key, count:value}; }
    > res = db.runCommand({
        mapreduce:"students",
        map:map,
        reduce:reduce,
        out:"students_res",
        finalize:f
     })
     
     
     
     部署 Replica Sets
     1、 创建数据文件存储路径
    [root@localhost ~]# mkdir -p /data/data/r0
    [root@localhost ~]# mkdir -p /data/data/r1
    [root@localhost ~]# mkdir -p /data/data/r2

    2、 创建日志文件路径
    [root@localhost ~]# mkdir -p /data/log

    3、创建主从 key 文件,用于标识集群的私钥的完整路径,如果各个实例的 key file 内容不一
    致,程序将不能正常用。
    [root@localhost ~]# mkdir -p /data/key
    [root@localhost ~]# echo "this is rs1 super secret key" > /data/key/r0
    [root@localhost ~]# echo "this is rs1 super secret key" > /data/key/r1
    [root@localhost ~]# echo "this is rs1 super secret key" > /data/key/r2
    [root@localhost ~]# chmod 600 /data/key/r*

    4、启动 3 个实例
    [root@localhost ~]# /Apps/mongo/bin/mongod --replSet rs1 --keyFile /data/key/r0 --fork --port
         28010 --dbpath /data/data/r0 --logpath=/data/log/r0.log --logappend
    [root@localhost ~]# /Apps/mongo/bin/mongod --replSet rs1 --keyFile /data/key/r1 --fork --port
         28011 --dbpath /data/data/r1 --logpath=/data/log/r1.log --logappend
    [root@localhost ~]# /Apps/mongo/bin/mongod --replSet rs1 --keyFile /data/key/r2 --fork --port
         28012 --dbpath /data/data/r2 --logpath=/data/log/r2.log --logappend
        
    5、配置及初始化 Replica Sets
    [root@localhost bin]# /Apps/mongo/bin/mongo -port 28010
    > config_rs1 = {_id: 'rs1', members: [
        {_id: 0, host: 'localhost:28010', priority:1}, --成员 IP 及端口, priority=1 指 PRIMARY
        {_id: 1, host: 'localhost:28011'},
        {_id: 2, host: 'localhost:28012'}]
        }
    > rs.initiate(config_rs1); --初始化配置
    > rs.status() -- 查看复制集状态
    > rs.isMaster() -- 查看 Replica Sets 状态

    6. 添加新的节点
      按照上述说的方法启动一个mongo,然后执行:
    rs1:PRIMARY> rs.add("localhost:28013")

    7. 删除节点
    rs1:PRIMARY> rs.remove("localhost:28013")



    Sharding 分片
    要构建一个 MongoDB Sharding Cluster,需要三种角色:
    (1) Shard Server
        即存储实际数据的分片,每个 Shard 可以是一个 mongod 实例,也可以是一组 mongod 实例构成的 Replica Set。
    (2) Config Server
        为了将一个特定的 collection 存储在多个 shard 中,需要为该 collection 指定一个 shard key,
    例如{age: 1} , shard key 可以决定该条记录属于哪个 chunk。 Config Servers 就是用来存储:
    所有 shard 节点的配置信息、每个 chunk 的 shard key 范围、 chunk 在各 shard 的分布情况、
    该集群中所有 DB 和 collection 的 sharding 配置信息。
    (3) Route Process
        这是一个前端路由,客户端由此接入,然后询问 Config Servers 需要到哪个 Shard 上查询或
    保存记录,再连接相应的 Shard 进行操作,最后将结果返回给客户端。

    sharding cluster创建步骤:
    (1) 启动shard server1
    mongod --shardsvr --port 20000 --dbpath E:MongoDBServerdatashards1 --logpath E:MongoDBServerdatashardlogs1.log --directoryperdb

    (2) 启动shard server2
    mongod --shardsvr --port 20001 --dbpath E:MongoDBServerdatashards2 --logpath E:MongoDBServerdatashardlogs2.log --directoryperdb --fork

    (3) 启动 Config Server
    mongod --configsvr --port 30000 --dbpath E:MongoDBServerdatashardconfig --logpath E:MongoDBServerdatashardlogconfig.log --directoryperdb --fork

    (4) 启动 Route Process
    mongos --port 40000 --configdb localhost:30000  --logpath E:MongoDBServerdatashardlog oute.log --chunkSize 1 --fork
    说明: chunkSize 这一项是用来指定 chunk 的大小的,单位是 MB,默认大小为 200MB

    (5) 登录到 mongos,添加 Shard 节点
    mongo admin --port 40000
    > db.runCommand({ addshard:"localhost:20000" }) -- 添加shard server1
    > db.runCommand({ addshard:"localhost:20001" })
    > db.runCommand({ enablesharding:"test" }) --设置分片存储的数据库
    > db.runCommand({ shardcollection: "test.users", key: { _id:1 }}) --设置分片的集合名称,且必须指定 Shard Key,系统会自动创建索引

    > db.users.stats() -- 查看数据库分片情况
    > db.runCommand({ listshards: 1 }) --列出所有的 Shard Server
    > printShardingStatus() --查看 Sharding 信息
    > db.runCommand({ addshard:"localhost:20002" }) --新增一个分片
    > db.runCommand({"removeshard" : "localhost:20002"}) -- 可以间断地运行此命令,以查看其移除进度
     

  • 相关阅读:
    IOS:个人笔记|UI_UITableView的优化
    IOS:个人笔记|UI_UITableView
    java基础知识记录(2)
    斐波那契数列
    字符串中数字排序,给定一个字符串“12 33 31 42 ”,或者键盘输入,进行排序
    java基础知识记录(1)
    【Unity】实验二 游戏场景搭建
    Error:java: Compilation failed: internal java compiler error 解决
    Github + Picgo + Typora 让笔记远走高飞
    remote: Incorrect username or password ( access token ) fatal: Authentication failed for
  • 原文地址:https://www.cnblogs.com/langfanyun/p/6059672.html
Copyright © 2011-2022 走看看