3 Nov 2017

MongoDB非关系数据库

MongoDB 是一个基于分布式文件存储的非关系数据库。存储格式是bson

安装

  1. 下载安装包
    下载完以后直接安装
    使用ssl:mongodb://localhost/?ssl=true
  2. 设置
    1. 在data文件夹下新建db、log文件夹
    2. log文件夹下创建一个MongoDB.log文件
    3. 命令:
      mongod --dbpath "xxx\MongoDB\Server\3.2\data\db" --logpath "xxx\MongoDB\Server\3.2\data\log\MongoDB.log"  --port 27017 --install --serviceName "MongoDB"  --directoryperdb
      

      指定每个DB都会新建一个目录

    4. 输入exit或者ctrl+C退出。
  3. 连接: mongo 127.0.0.1:xxx
    默认连接到test数据库,说明连接成功了
  4. 图形化连接工具 MongoCola、Robomongo
  5. 启动mongodb服务
    d:\mongodb\bin>NET START MongoDB
  6. 关闭服务和删除进程
    d:\mongodb\bin>NET stop MongoDB(关闭服务)
    d:\mongodb\bin>mongod --dbpath "d:\mongodb\data\db" --logpath "d:\mongodb\data\log\MongoDB.log" --remove --serviceName "MongoDB" (删除,注意不是–install了)
  7. 配置MongoDB的环境变量 %MongoDB%\Server\3.2\bin
    启动mongod --dbpath D:\work\MongoDB\data --logpath D:\work\MongoDB\log\mongodb.log
  8. 使用配置文件设置mongod的参数
    D:\work\MongoDB下新建文件mongodb.conf,在文件中写
    dbpath = D:\work\MongoDB\data
    logpath = D:\work\MongoDB\log\mongodb.log
    

    使用命令:mongod -f D:\work\MongoDB\mongodb.conf

  9. linux: 启动 MongoDB 服务, 作为 Linux 服务随机启动
    vi /etc/rc.local //使用vi 编辑器打开配置文件,并在其中加入下面一行代码
    /usr/local/mongo/bin/mongod --dbpath=/data/db/ --logpath=/data/logs/mongodb.log --logappend&
    安装完成后, 可以使用 pkill mongod 来结束

数据逻辑结构

● MongoDB 的文档(document),相当于关系数据库中的一行记录
● 多个文档组成一个集合(collection),相当于关系数据库的表
● 多个集合(collection),逻辑上组织在一起,就是数据库(database)
● 一个 MongoDB 实例支持多个数据库(database)
● 默认端口: 27017

用户管理

  1. 修改启动MongoDB时要求用户验证
    把MongoDB服务删除,再重新添加服务(–auth)
    mongod --dbpath "D:\work\MongoDB\data" --logpath "D:\work\MongoDB\log\mongodb.log" --install --serviceName "MongoDB" --auth
  2. 创建用户,并使用创建的用户登录
    使用db.auth("user","pwd")进行用户验证
    因为数据库中没有用户,所以需要先使用无用户验证的方式启动数据,在admin数据库下新建用户。只能在当前数据库登录
    db.createUser({user:"admin", pwd:"admin", roles:[{role:"角色名,", db:"对指定数据库的操作"}]})
    在使用用户验证的方式启动数据库,在数据库admin中,使用admin登录
    db.auth("admin","admin") 状态1表示验证成功,0表示验证失败
    创建用户默认给当前使用的数据下创建用户
  3. 查看当前数据下的用户
    1. show users 显示当前数据库下所有的用户(用户管理权限)
    2. db.getUsers() 查看所有的用户
    3. db.getUser("user") 查询指定用户的具体信息
  4. 修改用户信息
    db.changeUserPassword("user", "newpwd"),修改密码
    db.updateUser("user", {roles:[{role:"", db:""}]})修改用户信息
    db.grantRolesToUser("user", [{role:"", db:""}])追加角色
    db.revokeRolesFromUser("user", [{role:"", db:""}])取消角色
  5. 删除用户
    db.dropUser("user") 删除指定用户
    db.dropAllUsers() 删除当前数据下所有用户
    db.addUser(username, password) 添加用户
    db.removeUser(username) 删除用户

附:常用内置角色说明

数据库用户角色(每个数据库都有的角色)
read 对non-system集合的读取权限,以及以下system集合的读取权限:system.indexes,system.js,system.namespaces
readWrite 对non-system集合的读写权限,以及system.js上的读写权限
数据库管理角色(每个数据库都包含的数据管理角色)
dbAdmin 完成管理性任务的权限,比如schema相关任务、索引、统计信息收集。不能用于管理用户和角色
dbOwner 管理数据库需要的所有权限。包含(readWrite、dbAdmin、userAdmin角色的权限)
userAdmin 在当前数据库创建和修改角色和用户的权限
集群管理角色
admin数据库包含以下角色用于管理整个系统,而不是只针对单个数据库
clusterAmin 提供集群管理的最大权限。包含了clusterManager、clusterMonitor、hostManager角色的权限
clusterManager 管理和监控集群,可以访问local和config数据库。
clusterMonitor 对集群的读权限
hostManager 管理和健康servers
备份和还原角色
admin数据库包含以下角色用于备份和还原数据
backup 备份权限
restore 还原权限
all-database roles
admin数据提供以下角色,对所有数据库都有效。
readAnyDatabase 提供对所有数据库的读权限
readWriteAnyDatabase 提供对所有数据库的写权限
userAdminAnyDatabase 提供对所有数据库用户的管理权限
dbAdminAnyDatabase 对所有数据库的dbAdmin权限
超级角色
root 拥有最高权限

常用命令

show dbs 显示所有的数据库
use dbname 切换到某一个数据中(大小写敏感)
show collections 显示当前数据库中所有的集合
db.集合名.find() 查询当前数据库中某一个集合下所有的数据
db.集合名.insert({"键": "值", ...}) 给当前数据库中某一个集合添加数据
db.集合名.drop() 删除某一个集合
db.dropDatabase() 删除当前数据库
db || db.getName() 显示当前数据库
show profile 显示当前 system.profile { $rename : { old_field_name : new_field_name } 字段重命名 示例:
db.student.insert([{"_id": 2, "name": "lisi"},{"_id": 3, "name": "wangwu"}, {"_id": 4, "name": "zhaoliu", "age": 28}])
for(var i=; i<; i++){db.fortest.insert({num: i})}

索引 ensureIndex()

  1. 普通索引 db.persons.ensureIndex({name:1});
    db.factories.insert({name: "xyz", metro: {city: "New York", state: "NY"}});
  2. 文档式索引 db.factories.ensureIndex({metro : 1});
  3. 嵌入式索引 db.factories.ensureIndex({"metro.city": 1});
  4. 组合索引 db.things.ensureIndex({name: -1, qty: 1});
  5. 唯一索引 db.user.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
    当一个记录被插入到唯一性索引文档时,缺失的字段会以null为默认值被插入文档
    db.things.save({lastname: "Smith"});
    下面这个操作将会失败,因为 firstname 上有唯一性索引,值为 null
    db.things.save({lastname: "Jones"});
  6. 查看索引 db.persons.getIndexes();
  7. 删除所有索引 db.collection.dropIndexes();
  8. 删除单个索引 db.collection.dropIndex({x: 1, y: -1});

增、删、改、查

  1. db.Client.insert({_id:new ObjectId(),Name:"xx",Sex:0,Created:new Date()});
    _id可以不带,系统会自己给你加上
  2. db.Client.update({Name:"xxx"},{$set:{Sex:1}},{upsert:true});
    如果Client表中没有Name : "xxx"的记录则会新加一条记录,如果有记录则更新 Sex: 1
    upsert 为true的意思是如果没有找到对应的记录则添加,如果找到则更新。该参数默认情况下为false,则没有找到数据就不添加,也不更新
  3. db.Client.save({Name:"xx",Sex:0,Created:new Date()});
    (没有集合时会新建)添加时不用带_id,有_id时若有数据会进行更新
  4. 特别提醒: new ObjectId() 是新建ObjectId的意思 new Date() 获取当前时间,系统默认的是0时区

  1. db.Client.remove({Name:"xxx"});
    删除满足{Name:”xxx”}条件的所有数据
  2. db.collection.deleteOne()删除满足条件的第一个文档
  3. db.collection.deleteMany() 删除满足条件的所有文档,返回删除数量
  4. db.users.remove()==.remove({}) 删除users集合下所有数据
  5. db.users.drop()db.runCommand({"drop","users"}) 删除集合users
  6. db.runCommand({"dropDatabase": 1}) 删除当前数据库
  7. 执行remove时会有 update操作这个记录,可能删不掉db.stu.remove({rating:{$lt:3.0},$atomic:true})
  8. db.users.remove({query}, justOne) justOne:是否只删除查询到的第一条数据

  1. db.users.update({Name:"xxx"},{$set:{Sex:0}},upsert,{multi:true})
    1. 查询条件:{Name:”xxx”}
    2. 修改项:{$set:{Sex:0}} 其中$set可以更换为其他修改器 $set为更新,(存在键则修改,如果不存在键则添加),$inc为累加($inc不能应用于非数字数据) $unset 删除指定的列 其他修改器:$push $ne $addToSet $pop $pull
    3. upsert:如果不存在查询条件查出的记录,是否插入一条数据,默认是false
    4. 是否批量更新:{multi:true}
  2. db.users.save({_id:new ObjectId("574f"),Name:"xx",Sex:0,Created:new Date()}); 带上_id就可以更新指定id的所有列 特别提醒:如果用save进行保存时少了Created列,更新后的数据就会没有Created列
  3. db.users.findAndModify({query:{Sex:0},update:{$set:{Sex:1}}}); findAndModify 更新并返回更新的数据 查询条件:query为键,查询条件为值 修改项:update为键,修改列和项为值,如上所示,其中$set也可更换为其他修改器 需要注意的是,如果查询结果是多个,它只会更新满足条件的第一个文档并返回
  4. db.student.update({_id:7}, {$inc:{age:-1}}) $inc:在原来的基础上加多少
  5. db.student.update({_id:7},{$unset:{age:1}}) $unset:去掉某个键

  1. db.users.find() 查找users集合中所有数据
  2. db.users.findOne() 查找users集合中的第一条数据
  3. db.collection.find({ "key" : value }) 查找key=value的数据
  4. db.collection.find({ "key" : { $gt: a , $lt: b } }) 查找a < key <b
  5. db.collection.find({ "key" : { $mod : [ 10 , 1 ] } })===.find( "this.key%10==1" ) 取模运算,即key除以10余数为1的数据
  6. db.collection.find({ "key" : { $size: 1 } })==.find( { $where : function() { return this.key == 3 } } ); ==.find( function() { return this.key == 3 } ); $size 数组数量、尺寸,条件相当于key的值的数量是1
  7. db.collection.find({ "key" : { $exists : true|false } }) $exists 字段存在,true返回存在字段key的数据,false返回不存在字度key的数据
  8. db.collection.find({ "key": /^val.*val$/i })正则,类似like;“i”忽略大小写,“m”支持多行
  9. db.collection.find({ "key.subkey" :value }) 内嵌对象中的值匹配,注意:”key.subkey”必须加引号
  10. db.collection.find({ "key": { $not : /^val.*val$/i } }) 这是一个与其他查询条件组合使用的操作符,不会单独使用。上述查询条件得到的结果集加上$not之后就能获得相反的集合
  11. db.集合名称.find({查询条件},{指定键})查询指定键,指定键:1表示显示,0表示不显示,_id默认显示
  12. db.集合名称.find({查询条件},{指定键}).skip(6).limit(3).sort({age:1})1升序,2降序
  13. .find({name: /si\b/})==.find( { name : { $regex : 'u.*4$', $options : 'i', $nin : [ 'user4' ] } } ).limit(2); 正则表达式
  14. 逻辑运算符
    $lt:<
    $lte:<=
    $gt:>
    $gte:>=
    $ne:!=
    $in:包含  $all
    $nin:不包含
    $or:或者  .find({$or:[{age:{$lt:29}}, {name:"sunba"}]})   $nor 跟 $or 相反
    null:空值     .find({sex: null})
    $type:键是某种类型的
            .find({name: {$type: 2}})           
            ● Double : 1 ● String : 2 ● Object : 3 ● Array : 4 ● Binary data : 5 ● Object id :7 ● Boolean :8 ● Date :9 ● Null : 10 ● Regular expression : 11 ● JavaScript code : 13 
            ● Symbol : 14 ● JavaScript code with scope : 15 ● 32-bit integer : 16 ● Timestamp : 17 ● 64-bit integer : 18 ● Min key : 255 ● Max key : 127
    

排序

db.collection.find().skip(3).limit(5).count(true)== db.user.find({}, {}, 3, 5).count(true); 跳过3条数据再取5条数据,要获得实际返回的结果数,需要一个参数true,否则返回的是符合查询条件的结果总数

数组类型

  1. db.student.update({_id: 7},{$push:{skill:"java"}})
    不存在键时,创建数组类型的键;该键是数组类型时,追加数据,否则报错
  2. db.student.update({_id: 7},{$pushAll:{skill:["js","C++","java"]}})
    批量往数组中追加
  3. db.student.update({_id:7},{$addToSet:{skill:"mongodb"}})
    数组中有该值时不追加,没有该值时追加
  4. db.student.update({_id:7},{$pop:1})
    删除数组的第一个(值为-1)或最后一个(值为1)元素
  5. db.student.update({_id:7},{$pull:{field:_value}})
    删除某一个符合 _value 检索条件的记录
  6. db.student.update({_id:7},{$addToSet:{pullAll:{field:_value}}})
    删除数组中多个指定的数值

分组

db.coll.group( { 
       cond     : {filedconditions}, //查询条件
       key      : {filed: true}, //对那个字段进行
       initial  : {count: 0, total_time:0}, //初始化group计数器
       reduce   : function(doc, out){ }, //通常做统计操作
       finalize : function(out){} //通常都统计结果进行进一步操作
} );

去重

  1. .distinct("zip-code");
  2. command 模式: db.runCommand( { distinct: 'addresses', key: 'zip-code' } )
    db.comments.save( { "user" : { "points" : 25 } } )

$elemMatch

t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) ==.find({"x.a":1,"x.b":{$gt:1}})

$slice

  1. db.posts.find({}, {comments:{$slice: 5}}) // 前5条评论
  2. db.posts.find({}, {comments:{$slice: -5}}) //后5条评论
  3. db.posts.find({}, {comments:{$slice: [20, 10]}}) // 跳过20条, limit 10
  4. db.posts.find({}, {comments:{$slice: [-20, 10]}}) // 后20条, limit 10

特殊操作符:$

  1. db.t.update( { x : 2 }, { $inc : { "x.$": 1 } }, false, true);
    $ 操作符代表查询记录中第一个匹配条件的记录项
  2. db.t.update({x:3},{$unset:{"x.$":1}})
    在数组中用 $ 配合 $unset操作 符的时,效果是把匹配的元素变成了null

Tags: