mongodb

首页mongodb
10
Aug
0

mongodb常用命令学习五 (副本,分片)

QQ截图20160810103808.png
主从复制(暂无菊花链,互相复制):
建立主机
mongod --dbpath c:mongodbdata --master

建立分机
mongod --dbpath c:mongodbslave --port 1000 --slave --source localhost:27017

一些参数
c:mongodbbin>mongod --dbpath c:mongodbslave --port 1000 --slave

--source localhost:27017 --only mydb --slavedelay 60 --fastsync --autoresync

only 只同步某库
slavedelay 延时同步 单位秒
fastsync 以主节点快照为基础启动,加快启动速度
autoresync 如果与主节点不同步了 则自动重来

副本集(未测试成功 参数不正确)
第一台 名字(blort) 第二台名字(morton:10002)
c:mongodbbin>mongod --dbpath c:mongodbslave -- port 1001 --replset blort/morton:10002
第二台
c:mongodbbin>mongod --dbpath c:mongodbslave -- port 1002 --replset blort/
第三台
c:mongodbbin>mongod --dbpath c:mongodbslave -- port 1001 --replset blort/morton:10002(morton:10001)

建立副本集后,SHELL里先初始化
测试不成功,后面的暂时用不到 就不学了 OH YEAH

分片(从有第一个服务器开始)

先启动服务器
mongod --dbpath c:mongodbdata
启动配置服务器
mongos --port 3000 --configdb localhost:27017
mongos --port 3000 --configdb localhost:27017,localhost:27018,localhost:27019

启动第二个服务器
mongod --dbpath c:mongodbslave --port 20001

连接SHELL
mongo localhost:30000/admin

添加分片:allowLocal参数 让它知道我们是在本地配置开发 ^_^
db.runCommand({addshard:"localhost:20001",allowLocal:true})

开启foo数据库的分片功能
db.runCommand({"enablesharding":"foo"})

对数据库foo的数据集合bar进行分片,以_id字段
db.runCommand({"shardcollection":"foo.bar","key":{"_id":1}})

添加副本集 (副本集挂了,自动会找主节点)
db.runCommand({"addshard":"foo/prod.example.com:27017"})

查询分片信息
use config
db.shards.find()

查询已经在分片上的数据库
db.databases.find()

查询分片块信息
db.chunks.find()

查询摘要信息
db.printShardingStatus()

移除分片,会把内容移到其它分片
db.runCommand({"removeshard":"localhost:10000"})

30
Jul
0

mongodb常用命令学习四 (管理)

守护进程方式启动
mongod --fork

开启http interface
mongod -- httpinterface

输出日志,而不是输出到命令行
mongod --logpath

配置文件
mongod --config c:mongodbabc.conf

port = 5586
fork = true
logpath = mongodb.log #注释

关闭服务器
use admin
db.shutdownServer()

取得服务器状态
db.runCommand({"serverStatus":1})

实时状态命令
mongostat

更改用户名
db.changeUserPassword('sa','sa')

分库用户名:第三参数为只允许读
db.addUser('test','test',true)

开启安全性检查--auth
mongod --dbpath c:mongodbdata --httpinterface --auth

开启安全检查后登陆
db.auth('sa','sa')

删除用户(测试失败)
db.system.users.remove({"test":"test"})

禁用管理端口和禁止JAVASCRIPT执行
--noscripting --nohttpinterface

热备份
mongodump -d mydb -o backup -u sa -p sa

热还原 --drop 先删后建
mongorestore -d mydb --drop backup/mydb -u sa -p sa

上锁 准备备份
db.runCommand({"fsync":1,"lock":1})

备份完 减锁
db.$cmd.sys.unlock.findOne()
db.currentOp() --此句确保减锁成功

未正常停止过的服务器,必须启动修复,要不然不能热备份
mongodb --repair

或者
db.repairDatabase()

再或者
db.runCommand({"repairDatabase":1})

29
Jul
0

mongodb常用命令学习三 (数据索引,游标)

表的几种操作:其实可以不用啦
use ChatRoom

show collections

创建表
db.createCollection("Account")
db.createCollection("Test",{capped:true, size:10000}) { "ok" : 1 } --capped 不可修改

修改表名
db.Account.renameCollection("Account1")

db.posts.insert({"s":{"d":"k"}})

子节点查询
db.posts.find({"s.d":"k"})

db.number.insert({"id":1,"results":[82,85,88]})
db.number.insert({"id":2,"results":[75,88,89]})

全部大于等于80或者全部小于85的记录
db.number.find({results:{$elemMatch:{$gte:80,$lt:85}}}) --返回第一行数据

去重
db.users.distinct('name');

用任意代码过滤结果 只要返回TRUE 记录被返回 速度特别慢 不到万不得已 不用
db.foo.find({$where:"function(){return this.spinach + this.watermelon == 8;}"}

游标 (此法 一次显示一条数据)
var cursor = db.foo.find()
while (cursor.hasNext()){

   obj = cursor.next();
    }

显示所有:

 var cursor = db.foo.find()
 cursor.forEach(function(x){
          print(x.apple);
          });

定义

 var cursor = db.foo.find().sort({"apple":1}).limit(1).skip(1);
 cursor.next() 显示

是否还有记录

 cursor.hasNext();

限制返回记录数
limit(1)

跳过前面几条数据
skip(3)

排序 apple升序 banana降序
db.foo.find().sort({apple:-1,banana:1})

随机数字段 产生一个0-1的数
Math.random()

文档变大后会移到末位,游标可能再次返回它,所以加 $snapshot 加快照

建立索引 水果 升序
db.foo.ensureIndex({"apple":1})

如果多列中有一列没有索引 就得不到性能提升

db.foo.ensureIndex({"apple":1,"banana":1})

多字段索引 只有用字段顺序前面的才会 用到索引 用中间的不会用到索引

唯一键:
db.foo.ensureIndex({"banana":1},{"name":"abcIndex","unique":true})

唯一键和清除重复:
db.foo.ensureIndex({"banana":1},{"unique":true,"dropDups":true})

查看查询用到的索引信息:
db.foo.find().explain()

删除索引
db.runCommand({"dropIndexes":"foo","index":"*"})

执行时间太长,移到后台执行
db.foo.ensureIndex({"apple":1},{"background":true})

地图索引(双维度 值范围-180 到 180):
db.foo.ensureIndex({"gps":"2d"})
db.foo.ensureIndex({"gps":{"x":-180,"y":180}})

选择座标附近的位置 没有limit就默认100条
db.foo.find({"gps":{"$near":[40,-73]}})

还能返回原点距离:
db.runCommand({geoNear:"map",near:[40,73],num:10})

查询矩形框内的记录
db.foo.find({"gps":{"$within":{"$box":[[10,20],[15,30]]}}})

统计函数:
db.foo.count({"apple":1})

过滤重复:
db.runCommand({"distinct":"foo","key":"apple"})

26
Jul
0

MongoDB高级查询用法大全

版本一:

1 ) . 大于,小于,大于或等于,小于或等于

$gt:大于
$lt:小于
$gte:大于或等于
$lte:小于或等于

例子:
db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value
db.collection.find({ "field" : { $lt: value } } ); // less than : field < value
db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value
db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
如查询j大于3,小于4:

db.things.find({j : {$lt: 3}});
db.things.find({j : {$gte: 4}});
也可以合并在一条语句内:

db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
2) 不等于 $ne

例子:

db.things.find( { x : { $ne : 3 } } );
3) in 和 not in ($in $nin)

语法:
db.collection.find( { "field" : { $in : array } } );
例子:

db.things.find({j:{$in: [2,4,6]}});
db.things.find({j:{$nin: [2,4,6]}});

4) 取模运算$mod

如下面的运算:
db.things.find( "this.a % 10 == 1")
可用$mod代替:

db.things.find( { a : { $mod : [ 10 , 1 ] } } )

5) $all

$all和$in类似,但是他需要匹配条件内所有的值:

如有一个对象:

{ a: [ 1, 2, 3 ] }
下面这个条件是可以匹配的:

db.things.find( { a: { $all: [ 2, 3 ] } } );
但是下面这个条件就不行了:

db.things.find( { a: { $all: [ 2, 3, 4 ] } } );

6) $size

$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:

下面的语句就可以匹配:
db.things.find( { a : { $size: 1 } } );
官网上说不能用来匹配一个范围内的元素,如果想找$size<5之类的,他们建议创建一个字段来保存元素的数量。

You cannot use $size to find a range of sizes (for example: arrays with more than 1 element). If you need to query for a range, create an extra size field that you increment when you add elements.

7)$exists

$exists用来判断一个元素是否存在:

如:

db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回
db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
8) $type
$type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。

db.things.find( { a : { $type : 2 } } ); // matches if a is a string
db.things.find( { a : { $type : 16 } } ); // matches if a is an int
9)正则表达式

mongo支持正则表达式,如:
db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
10) 查询数据内的值

下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。
db.things.find( { colors : "red" } );
11) $elemMatch

如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素:

t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } )
{ "_id" : ObjectId("4b5783300334000000000aa9"),

"x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]
}
$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。
注意,上面的语句和下面是不一样的。

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

$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 }

12) 查询嵌入对象的值
db.postings.find( { "author.name" : "joe" } );
注意用法是author.name,用一个点就行了。更详细的可以看这个链接: dot notation

举个例子:

db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})

如果我们要查询 authors name 是Jane的, 我们可以这样:

db.blog.findOne({"author.name" : "Jane"})

如果不用点,那就需要用下面这句才能匹配:

db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
下面这句:

db.blog.findOne({"author" : {"name" : "Jane"}})
是不能匹配的,因为mongodb对于子对象,他是精确匹配。

13) 元操作符 $not 取反

如:

db.customers.find( { name : { $not : /acme.*corp/i } } );
db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
mongodb还有很多函数可以用,如排序,统计等,请参考原文。

mongodb目前没有或(or)操作符,只能用变通的办法代替,可以参考下面的链接:

http://www.mongodb.org/display/DOCS/OR+operations+in+query+expressions

版本二:
shell 环境下的操作:

  1. 超级用户相关:

    1. 进入数据库admin

      use admin

    2. 增加或修改用户密码

    db.addUser('name','pwd')

    1. 查看用户列表

    db.system.users.find()

    1. 用户认证

    db.auth('name','pwd')

    1. 删除用户

    db.removeUser('name')

    1. 查看所有用户

    show users

    1. 查看所有数据库

    show dbs

    1. 查看所有的collection

    show collections

    1. 查看各collection的状态

    db.printCollectionStats()

    1. 查看主从复制状态

    db.printReplicationInfo()

    1. 修复数据库

    db.repairDatabase()

    1. 设置记录profiling,0=off 1=slow 2=all

    db.setProfilingLevel(1)

    1. 查看profiling

    show profile

    1. 拷贝数据库

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

    1. 删除collection

    db.mail_addr.drop()

    1. 删除当前的数据库

    db.dropDatabase()

  2. 增删改

    1. 存储嵌套的对象

      db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
      
    2. 存储数组对象

      db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
      
    3. 根据query条件修改,如果不存在则插入,允许修改多条记录

      db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)

    4. 删除yy=5的记录

      db.foo.remove({'yy':5})

    5. 删除所有的记录

      db.foo.remove()

  3. 索引

    1. 增加索引:1(ascending),-1(descending)

    2. db.foo.ensureIndex({firstname: 1, lastname: 1}, {unique: true});
    3. 索引子对象

    4. db.user_addr.ensureIndex({'Al.Em': 1})
    5. 查看索引信息

    6. db.foo.getIndexes()
    7. db.foo.getIndexKeys()
    8. 根据索引名删除索引

    9. db.user_addr.dropIndex('Al.Em_1')
  4. 查询

    1. 查找所有

    1. db.foo.find()
    2. 查找一条记录

    3. db.foo.findOne()
    4. 根据条件检索10条记录

    5. db.foo.find({'msg':'Hello 1'}).limit(10)
    6. sort排序

    7. db.deliver_status.find({'From':'ixigua@sina.com'}).sort({'Dt',-1})

      1. db.deliver_status.find().sort({'Ct':-1}).limit(1)
    8. count操作

    9. db.user_addr.count()
    10. distinct操作,查询指定列,去重复

    11. db.foo.distinct('msg')
    12. ”>=”操作

    13. db.foo.find({"timestamp": {"$gte" : 2}})
    14. 子对象的查找

    15. db.foo.find({'address.city':'beijing'})
  5. 管理

    1. 查看collection数据的大小

    2. db.deliver_status.dataSize()
    3. 查看colleciont状态

    4. db.deliver_status.stats()
    5. 查询所有索引的大小

    6. db.deliver_status.totalIndexSize()
  1. 高级查询

条件操作符
$gt : >
$lt : <
$gte: >=
$lte: <=
$ne : !=、<>
$in : in
$nin: not in
$all: all
$not: 反匹配(1.3.3及以上版本)

查询 name <> "bruce" and age >= 18 的数据
db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});

查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据
db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});

查询 age in (20,22,24,26) 的数据
db.users.find({age: {$in: [20,22,24,26]}});

查询 age取模10等于0 的数据
db.users.find('this.age % 10 == 0');
或者
db.users.find({age : {$mod : [10, 0]}});

匹配所有
db.users.find({favorite_number : {$all : [6, 8]}});
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] }
可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }

查询不匹配name=B*带头的记录
db.users.find({name: {$not: /^B.*/}});
查询 age取模10不等于0 的数据
db.users.find({age : {$not: {$mod : [10, 0]}}});

返回部分字段

选择返回age和_id字段(_id字段总是会被返回)
db.users.find({}, {age:1});
db.users.find({}, {age:3});
db.users.find({}, {age:true});
db.users.find({ name : "bruce" }, {age:1});
0为false, 非0为true

选择返回age、address和_id字段
db.users.find({ name : "bruce" }, {age:1, address:1});

排除返回age、address和_id字段
db.users.find({}, {age:0, address:false});
db.users.find({ name : "bruce" }, {age:0, address:false});

数组元素个数判断
对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录
匹配db.users.find({favorite_number: {$size: 3}});
不匹配db.users.find({favorite_number: {$size: 2}});

$exists判断字段是否存在
查询所有存在name字段的记录
db.users.find({name: {$exists: true}});
查询所有不存在phone字段的记录
db.users.find({phone: {$exists: false}});

$type判断字段类型
查询所有name字段是字符类型的
db.users.find({name: {$type: 2}});
查询所有age字段是整型的
db.users.find({age: {$type: 16}});

对于字符字段,可以使用正则表达式
查询以字母b或者B带头的所有记录
db.users.find({name: /^b.*/i});

$elemMatch(1.3.1及以上版本)
为数组的字段中匹配其中某个元素

Javascript查询和$where查询
查询 age > 18 的记录,以下查询都一样
db.users.find({age: {$gt: 18}});
db.users.find({$where: "this.age > 18"});
db.users.find("this.age > 18");
f = function() {return this.age > 18} db.users.find(f);

排序sort()
以年龄升序asc
db.users.find().sort({age: 1});
以年龄降序desc
db.users.find().sort({age: -1});

限制返回记录数量limit()
返回5条记录
db.users.find().limit(5);
返回3条记录并打印信息
db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)});
结果
my age is 18
my age is 19
my age is 20

限制返回记录的开始点skip()
从第3条记录开始,返回5条记录(limit 3, 5)
db.users.find().skip(3).limit(5);

查询记录条数count()
db.users.find().count();
db.users.find({age:18}).count();
以下返回的不是5,而是user表中所有的记录数量
db.users.find().skip(10).limit(5).count();
如果要返回限制之后的记录数量,要使用count(true)或者count(非0)
db.users.find().skip(10).limit(5).count(true);

分组group()
假设test表只有以下一条数据
{ domain: "www.mongodb.org"
, invoked_at: {d:"2009-11-03", t:"17:14:05"}
, response_time: 0.05
, http_action: "GET /display/DOCS/Aggregation"
}
使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count;
db.test.group(
{ cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
, key: {http_action: true}
, initial: {count: 0, total_time:0}
, reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
, finalize: function(out){ out.avg_time = out.total_time / out.count }
} );

[
{
"http_action" : "GET /display/DOCS/Aggregation",
"count" : 1,
"total_time" : 0.05,
"avg_time" : 0.05
}
]

16
Jul
0

mongodb常用命令学习二 (数据查询)

查找数据就立即修改,删除,等

ps = db.runCommand({"findAndModify":"process",

  "query":{"status":"READY"},
  "sort":{"priority":-1},
  "update":{"$set":{"status":"RUNNING"}},
  "remove":true,
  "new":true  是否返回修改后数据 还是修改前数据  默认修改前
  ).value

过滤器:

start = new Date("2010-01-01")
db.client.find({"birthday":{$lt:start}})

$lt < $lte <= $gt > $gte >= $ne <> $in in[5,7,8] $or

db.client.find({$or:[{"age":25},{"birthday":new Date("2013-05-07")}]})

db.client.find({$or:[{"age":25},{"birthday":{$lt:start}}]})

$mod $not

如果not和age交换 则报错 说明不能直接取反
db.client.find({"age":{"$not":{"$mod":[5,1]}}})

除了返回KANKAN为NULL的值 还会返回缺少这个字段的记录
db.client.find({"kankan":null})

这样会先判断是否包含该字段
db.client.find({"kankan":{"$in":[null],"$exists":true}})

正则表达式:所有含有i的记录
db.client.find({"name":/i/i})

可以为前缀型正则表达式创建索引(高级用法)

数组查询:
db.food.insert({"fruit":["banana","apple","peach"]})
db.food.find({"fruit":"apple"})

数组多值匹配:
db.food.insert({"fruit":["banana","apple","orange"]})
db.food.insert({"fruit":["banana","apple","pear"]})
$all
db.food.find({"fruit":{$all:["apple","banana"]}})

指定数据长度:
db.food.find({"fruit":{$size:2}})

此种用法,未测试成功
db.food.update({"$push":{"fruit":"orange"},"$inc":{"size":1}})

表的几种操作:其实可以不用啦
use ChatRoom

show collections

创建表
db.createCollection("Account")
db.createCollection("Test",{capped:true, size:10000}) { "ok" : 1 } --capped 不可修改

修改表名
db.Account.renameCollection("Account1")