MongoDB笔记

0.json基本数据格式
 
JSON 对象在花括号中书写:
{ "firstName":"John" , "lastName":"Doe" }

 

JSON 数组在方括号中书写:

数组可包含多个对象:

 

{
    "employees": [
        { "firstName":"John" , "lastName":"Doe" },
        { "firstName":"Anna" , "lastName":"Smith" },
        { "firstName":"Peter" , "lastName":"Jones" }
    ]
}

在上面的例子中,对象 "employees" 是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。

 
 
 

1、安装配置

下载解压到目录,新建data目录存放数据库,log存放日志
创建个配置文件mongodb.conf
port=10001
dbpath=/usr/lib64/mongodb/data/db
logpath=/usr/lib64/mongodb/data/log/mongodb.log
logappend=true
开启server:./bin/mongod -f mongod.conf
开启client:./bin/mongo  host:port
 

2、创建用户

3.0版本
use admin
db.createUser({user:"yearnfar",pwd:"123456",roles:['root']})
修改密码
db.changeUserPassword("username","newpassword")
查看用户信息
db.runCommand({userInfo:"kangw"}) 
验证用户
db.auth("username","pwd")
 
 

3、与Mql对照

MySQL

MongoDB

说明

mysqld

mongod

服务器守护进程

mysql

mongo

客户端工具

mysqldump

mongodump

逻辑备份工具

mysql

mongorestore

逻辑恢复工具

 

db.repairDatabase()

修复数据库

mysqldump

mongoexport

数据导出工具

source

mongoimport

数据导入工具

grant * privileges on *.* to …

Db.addUser()【老版本】

Db.auth()

新建用户并权限

show databases

show dbs

显示库列表

Show tables

Show collections

显示表列表

Show slave status

Rs.status

查询主从状态

Create table users(a int, b int)

db.createCollection("mycoll", {capped:true,

size:100000}) 另:可隐式创建表。

创建表

Create INDEX idxname ON users(name)

db.users.ensureIndex({name:1})

创建索引

Create INDEX idxname ON users(name,ts DESC)

db.users.ensureIndex({name:1,ts:-1})

创建索引

Insert into users values(1, 1)

db.users.insert({a:1, b:1})

插入记录

Select a, b from users

db.users.find({},{a:1, b:1})

查询表

Select * from users

db.users.find()

查询表

Select * from users where age=33

db.users.find({age:33})

条件查询

Select a, b from users where age=33

db.users.find({age:33},{a:1, b:1})

条件查询

select * from users where age<33

db.users.find({'age':{$lt:33}})

条件查询

select * from users where age>33 and age<=40

db.users.find({'age':{$gt:33,$lte:40}})

条件查询


select * from users where a=1 and b='q'

db.users.find({a:1,b:'q'})

条件查询

select * from users where a=1 or b=2

db.users.find( { $or : [ { a : 1 } , { b : 2 } ] } )

条件查询

select * from users limit 1

db.users.findOne()

条件查询

select * from users where name like "%Joe%"

db.users.find({name:/Joe/})

模糊查询

select * from users where name like "Joe%"

db.users.find({name:/^Joe/})

模糊查询

select count(1) from users

Db.users.count()

获取表记录数

select count(1) from users where age>30

db.users.find({age: {'$gt': 30}}).count()

获取表记录数

select DISTINCT last_name from users

db.users.distinct('last_name')

去掉重复值

select * from users ORDER BY name

db.users.find().sort({name:-1})

排序

select * from users ORDER BY name DESC

db.users.find().sort({name:-1})

排序

EXPLAIN select * from users where z=3

db.users.find({z:3}).explain()

获取存储路径

update users set a=1 where b='q'

db.users.update({b:'q'}, {$set:{a:1}}, false, true)

更新记录

update users set a=a+2 where b='q'

db.users.update({b:'q'}, {$inc:{a:2}}, false, true)

更新记录

delete from users where z="abc"

db.users.remove({z:'abc'})

删除记录

 

db. users.remove()

删除所有的记录

drop database IF EXISTS test;

use test

db.dropDatabase()

删除数据库

drop table IF EXISTS test;

db.mytable.drop()

删除表/collection

 

db.addUser(‘test’, ’test’)

添加用户

readOnly-->false

 

db.addUser(‘test’, ’test’, true)

添加用户

readOnly-->true

 

db.addUser("test","test222")

更改密码

 

db.system.users.remove({user:"test"})

或者db.removeUser('test')

删除用户


 

use admin

超级用户

 

db.auth(‘test’, ‘test’)

用户授权

 

db.system.users.find()

查看用户列表

 

show users

查看所有用户

 

db.printCollectionStats()

查看各collection的状态

 

db.printReplicationInfo()

查看主从复制状态

 

show profile

查看profiling

 

db.copyDatabase('mail_addr','mail_addr_tmp')

拷贝数据库

 

db.users.dataSize()

查看collection数据的大小

 

db. users.totalIndexSize()

查询索引的大小


4.插入数据
 

db.table.insert(....)  

 
db.table.insert({
    "name":"zhangsan",
    "age"   : 20,
    "like"   : [
        "apple","orange","phone"
    ]
})

5.update更新数据
db.collection.update(<query>,    <update>,{
     upsert:<boolean>,
     multi:<boolean>,
     writeConcern:<document>})

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
  • writeConcern :可选,抛出异常的级别。

db.user.update(
    {
        "name":"zhangsan"        //where
    },
    {                                            //set age=age+2 , heigh=200
        $inc:{"age":2},                
        $set:{"heigh":200}
    },
    {                                               //更新符合条件的全部
        "multi":true
    }
)
 
 
save()方法,替换已有数据
db.collection.save(<document>,{
     writeConcern:<document>})
db.col.save({"_id":ObjectId("56064f89ade2f21f36b03136"),"title":"MongoDB","description":"MongoDB 是一个 Nosql 数据库","by":"Runoob","url":"http://www.runoob.com","tags":["mongodb","NoSQL"],"likes":110})

7.删除数据
db.collection.remove(<query>,<justOne>    //设置删除的条数,没有就是全部)
2.6版本后
db.collection.remove(<query>,{
     justOne:<boolean>,
     writeConcern:<document>})

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档。
  • writeConcern :(可选)抛出异常的级别。
 
db.table.remove(
    {"name":"zhaosi"},        //where条件
    1                                    //只删除1条,无则是全部
)
 
 
8.查询数据
 
db.col.find({条件},{要获取的字段})
db.col.find().pretty()
格式化显示数据
db.col.findOne().pretty()
只显示一条
 
mongodb中的内置关键变量
Conditional Operators : $slice //切片
Conditional Operators : $lt <, $lte <=, $gt >, $gte >=
Conditional Operator : $ne //不等于
Conditional Operator : $in //属于
Conditional Operator : $nin //不属于
Conditional Operator : $mod //取模运算
Conditional Operator:   $all  //全部属于
Conditional Operator : $size //数量
Conditional Operator: $exists //字段存在
Conditional Operator: $type //字段类型
Conditional Operator: $or // 或
Regular Expressions //正则表达式
Value in an Array // 数组中的值
Conditional Operator: $elemMatch //要素符合
Value in an Embedded Object //内嵌对象中的值
Meta operator: $not //不是
Javascript Expressions and $where //
sort() //排序
limit() //限制取数据条数
skip() //跳过一定数值开始取
snapshot() //
count() // 数量
group() //分组
 
db.col.find({"by":"菜鸟教程","title":"MongoDB 教程"}).pretty()
WHERE by='菜鸟教程' AND title='MongoDB 教程'
 
db.col.find({$or:[{"by":"菜鸟教程"},{"title":"MongoDB 教程"}]}).pretty()
WHERE by='菜鸟教程' or title='MongoDB 教程'
 
db.col.find({"likes":{$gt:50}, $or:[{"by":"菜鸟教程"},{"title":"MongoDB 教程"}]}).pretty()
 'where likes>50 AND (by = '菜鸟教程' OR title = 'MongoDB 教程')'
 
db.col.find({likes :{$lt :200, $gt :100}})

Select*from col where likes>100 AND likes<200;

 
table.find({"name":{"$in":["abeen","ab","b"]}})
select * from table where name in (abeen,ab,b)
 
table.find({"age":{"$mod":[10,1]}})
查找age除10模等于1的
 
table.find({"name":{"$size": 6}}
取name元素数和$size数相同的信息

table.find({"name":{"$exists": True}}
取name存在的信息

table.find({"name":{"$type": 2}}
name类型为字符串的

type对应该类型表如下:


table.find({"name": {"$regex": r".*ee.*"}})
利用正则查询

table.find({"info.name": "abeen"})
查找内部对象info的name等于abeen的信息


table.find({"$query" : {"name": "abeen"}, "$orderby": { "age": 1/-1 }})
select *from table where name="abeen" order by age asc/desc
$query - 查询类似于sql中的 where
$orderby - 排序{x:1},1为升序 -1为降序

db.table.find().limit(10).skip(4)
select * from table limit 4,10
 

9.创建索引
db.table.ensureindex({key:1/-1}, {.其他选项} ,....,......);
1升序    -1降序
 
10.聚合
db.table.aggregate()



一、基础

1.文档
文档是mongodb的核心概念,类型与关系型数据库中的行。
多个键值有序的放置在一起便是文档。
mongodb不但区分类型,也区分大小写。
{  “foo":3   }
{    "foo":'3' }
{    "Foo":3  }
三个不同文档
文档中不能有重复的键
{    "Foo":3,“Foo":3  }
 
2.集合
集合就是一组文档。类似关系型数据库中的表
集合是无模式的,这意味着一个集合里面的文档可以是各式各样的。
{    "Foo":3  }
{    "Foo":3  ,“age":20}
 
3. db.getCollection("集合名称")
获取某个集合
db.getCollection("user").find()
 
因为某些集合的名称是关键词,或者是组合字符串得到的,可以用这个函数来操作
 
 
4.支持的数据类型              
null 
{"x":null}
布尔 
 {"x":true}
32位整数
shell中这个类型不可用,在js中仅支持64位浮点数,所以32位整数会被自动转换
64位整数
 shell也不支持这个类型,shell会使用一个特殊的内嵌文档来显示64位整数。
64位浮点数
{"x":3.14},{"x":3}这个也是浮点数。shell中的数字都是这种类型的。
字符串
{"x":"xxxx"}
符号  
shell中也不支持这种类型,会把此转换成字符串
对象id
 {"x":objectId()}
日期
{"x":new Date()}
正则表达式
{"x": /foobar/iU}
代码
{"x": function(){ alert('a')}}
二进制数据
二进制数据可以由任意字节的串组成,不过shell中无法使用
最大值
bson包括一个特殊类型,表示可能的最大值
最小值
bson包括一个特殊类型,表示可能的最小值
未定义
{"x":undefined}
数组
{"x":["a","b"]}
内嵌别的文档
{"x":{"foo":"bar"}}



5.修改
db.user.update({条件},{修改内容})
 
{ "_id" : ObjectId("5642ac0aca1b66a47448b8cf"), "name" : "zhangsan" }
 
5.1 //没有变量修饰,会直接替换内容
db.user.update(
    {"name":"kang"},
    {"info":{"age":20}} 
)
{ "_id" : ObjectId("5642abecca1b66a47448b8ce"), "name" : "kangkang", "info" : { "age" : 22 } }
5.2//有系统变量
db.user.update(
    {"name":"kang"},
    {$set:{"age":20}}        //更新字段,如果键不存在,则创建它。
)
{ "_id" : ObjectId("5642ac0aca1b66a47448b8cf"), "name" : "zhangsan", "info" : { "age" : 22 } , "age" : 20}
 
5.2.1
db.user.update(
    {"name":"kang"},
    {$unset:{"age":1}}    //删除指定的字段
)
{ "_id" : ObjectId("5642ac0aca1b66a47448b8cf"), "name" : "zhangsan", "info" : { "age" : 22 } }
 
5.2.2
$inc       字段自增
 
5.2.3
如果字段值为数组
db.user.update(
    {"name":"kang"},
    {$push:{"like":"apple"}}    //指定的键存在,则会向数组末尾加入一个元素。没有则创建一个新的数组
)
db.user.update(
    {"name":"kang"},
    {$push:{"like":"orange"}}  
)
{ "_id" : ObjectId("5642ac0aca1b66a47448b8cf"), "name" : "zhangsan", "info" : { "age" : 22 }, "like":["apple","orange"] }
 
 
5.2.4
db.user.update(
    {"name":"kang"},
    {$addToSet:{"like":"apple"}}    //插入到数组中,存在则忽略,可以避免值出现重复
)
{ "_id" : ObjectId("5642ac0aca1b66a47448b8cf"), "name" : "zhangsan", "info" : { "age" : 22 }, "like":["apple","orange"] }


操作字段数组中的值,可以这样db.user.update({"name":"kangkang"}, {$set:{"like.0","aaa"}})
定位符 $
 
 
6.查询
 
db.user.find({条件},{要显示的字段})
 
db.user.find({"name":"kang"}, {"age":1,"_id":0})
字段:值为1显示
_id字段默认会显示出来,值为0则不显示
 
and查询
db.user.find(
    {
        "age" : { "$gt":20 , "$lt":30 }
    }
)
where age>20 and age<30
 
in查询
db.user.find(
    {
        "age": { "$in": [1,2,3,4] }
    }
)
where age in (1,2,3,4)
 
or查询
db.user.find(
    {
        "$or":[  {"name":"kang"}, {"age":{"$lt":20}}  ]
    }
)
where  name="kang" or age<20
 
null匹配
null值不仅会匹配自身,如果其他条文档(行)中不存在此字段,也会被匹配,所以在查询的时候,还要判断这个是否存在
db.user.find(
    {
        "from":{ "$in":[null], "$exists":true }
    }
)
 
 
正则查询
db.user.find(
    {
        "name":/kang/i        //i忽略大小写
    }
)
 
数组查询
{ "_id" : ObjectId("564590848cd6fe155ab16ac7"), "fruit" : [ "apple", "banana", "peach" ] }
{ "_id" : ObjectId("564591518cd6fe155ab16ac8"), "fruit" : [ "cherry", "orange", "apple" ] }
查询有apple的
db.user.find(
    {
        "fruit":"apple"
    }
)
查询有apple和banana
db.user.find({
    "fruit": { "$all" : [ "apple","banana" ] }
})
查询数组长度等于3的
db.user.find({
    "fruit": { "$size" : 3 }
})
 
 
内嵌文档查询
db.comment.find().pretty()
{
    "_id" : ObjectId("5645978472a63ff99ddd6917"),
    "article" : 1,
    "comment" : [
        {
            "author" : "zhangsan",
            "score" : 1,
            "comment" : "zhangsanzhangsan"
        },
        {
            "author" : "zhaosi",
            "score" : 3,
            "comment" : "zhaosi44444"
        },
        {
            "author" : "zhaosi",
            "score" : 1,
            "comment" : "55555555555"
        },
        {
            "author" : "zhaosi",
            "score" : 2,
            "comment" : 6666666666666
        }
    ]
}
 
查author=zhangsan, score=1的评论
db.comment.find({"comment":{"$elemMatch":{"author":"zhangsan","score":1}}}).pretty()
 
 
skip().limit()
如果文档很多,会导致速度很慢,因此可以使用sort().limit()代替
也就是说先排序,再limit
 
随机获取一条记录
通常的做法:
先计算总条数,然后用随机函数产生一个这个之间的数,再skip()取
现在可以在插入数据的时候,加一个随机数的字段,然后用findOne()
 
高级查询
 
普通查询
    var    cursor = db.foo.find({"foo":"bar"}).sort({"age":-1})
     实际情况不是将{“foo”:"bar"}作为查询直接发给数据库,而是将查询包装在一个更大的文档中。shell会把查询从{“foo”:"bar"}转换成
     {
         "$query"    :    {"foo":"bar"},
        "$orderby" :    {"age": -1}   
     }
 
 
 
索引
 
绝大多数,优化mysql索引的技巧也同样适用于MongoDB
 
创建索引:
db.user.ensureIndex(
    {键:方向},
    {"name":索引名称}
)
db.user.ensureIndex({"age":1,“year":-1},{"name":"age_year"})
对于同一个集合,同样的索引只需要创建一次。反复创建是徒劳的
 
值为1或-1,与sort的作用一样,指定方向,如果索引只有一个键,则方向无关紧要。
只有使用索引前部的查询才能使用该索引。
 
为排序做索引
随着集合的增长,需要针对查询中大量的排序做索引,如果对没有索引的键调用sort,MongoDB需要将所有数据提取到内存来排序,一旦集合大到不能再内存中排序,MongoDB就会报错。
按照排序来索引以便让MongoDB按照顺序提取数据,这样就能排序大规模数据,而不必担心用光内存。
 
创建唯一索引
db.user.ensureIndex(
    {"name":1},
    {"unique":true}
)
 
如果插入了多个缺少该索引键的文档,则由于文档包含null值而导致插入失败
当为已有的集合创建索引,可能有些值已经有重复了,那么索引创建失败。
有时间希望将所有包含重复值的文档都删除掉。dropDups可以保留发现的第一个文档,而删除接下来的有重复值的文档。
db.user.ensureIndex(
    {"name":1},
    {"unique":true, "dropDups":true},
    {"background" : true}
)
background 可以使这个过程在后台完成,同时正常处理请求,要是没有,则数据库会阻塞建立索引期间的所有请求。
 
删除索引
db.runCommand(
    {"dropIndexes":表名},
    {"index":索引名称}     //为*表示删除全部索引
)
 
 
explain()分析
"cursor" : "BasiceCursor"
这说明查询没有使用索引
"nscanned":64
查了多少给文档
"n":64
返回的文档数量
"millis":0
毫秒数,查询时间
 
 

聚合查询
 
可以用来计算集合中文档的个数,复杂的可以利用MapReduce做复杂数据分析
 
db.foo.count()
返回集合中的总条数
 
distinct
 
 
 
主从复制
 
1.最基本的设置方式建立一个主节点和多个从节点。
开启主服务
    mongod   --dbpath  db/  --port 27001  --master
开启从服务
    mongod    --dbpath db/  --port 27002  --slave  --source  127.0.0.1:27001
 
如果过多个节点对单个主节点发起查询,会让其吃不消,所以实际中,不超过12个从节点
 
2.选项:
    --only
    在从节点上指定只复制特定某个数据库,默认复制所有的数据库
 
    --slavedelay
    用在从节点上,设置同步主节点的时间周期,通过延缓执行操作,可以恢复误删的文件
 
    --autoresync
    如果从节点与主节点不同了,则自动同步
 
    --oplogSize
    主节点oplog的大小,单位MB
 
3.添加,删除主源
  从节点启动时,不添加主服务源地址,而是随后添加
  启动
    mongod    --dbpath     db/    --port    27002    --slave
添加源
    use    local
    db.sources.insert(  {"host":"127.0.0.1:27001"}  )   
  修改源,则可以用insert,remove来完成
    db.sources.insert( {"host":"prod.example.com:27001"} )
    db.sources.remove( {"host":"127.0.0.1:27001"} )
 
so  easy  !~~
 
 
副本集
开启3台:
1/bin/mongod --dbpath=1/db/ --port=10001 --replSet=kang/127.0.0.1:10002
2/bin/mongod --dbpath=2/db/ --port=10002 --replSet=kang/127.0.0.1:10001
3/bin/mongod --dbpath=3/db/ --port=10003 --replSet=kang/127.0.0.1:10003
4/bin/mongod --dbpath=4/db/ --port=10004 --replSet=kang/127.0.0.1:10004
 
初始化副本集
随便进入一台的admin集合中
mongo 127.0.0.1:10002/admin
初始化命令:
db.runCommand({
    "replSetInitiate":
      {
            "_id":"kang",
            "members":
              [
                   {"_id":1, "host":"127.0.0.1:10001"},
                    {"_id":2, "host":"127.0.0.1:10002"},
              ]
      }
})
再添加一台
rs.add("127.0.0.1:10003")
添加一台仲裁机
rs.addArb("127.0.0.1:10004")
 
仲裁机会把1,2,3中一台指定为主服务,其他的为副,如果主挂了,仲裁机会把副中的一台再指定为主,主重启后变为副
 
在主从中,从服务是不能读的,需要开启rs.slaveOk(),从服务才可以读,但是从是不能写入的
 
 
分片







db.runCommand(
    {"addshard":"127.0.0.1:10001","allowLocal":true}
)




















posted @ 2015-11-20 11:32  悲惨的大爷  阅读(3129)  评论(0编辑  收藏  举报