特点
#
数据结构json(bson)
易写入,易修改
c++编写
分布式
介于关系数据库 和 非关系数据库之间
查询语句强
支持索引
bson格式
注意
#
document不能大于4Mb
可以非安全模式异步马上成功
每个连接用队列存储命令
数据结构定义
#
collection # 表
document # 记录
field(key, value) # 字段(field)与值(value)
与关系型数据库的区别
document中的field不要key俱全或一样
find()命令查询
bson的数据类型
#
#bson 是json的扩展
# 增加了数据类型
# 把json数据转换成二进制码存到文件
null
boolean
undefined
数组 # 如{gps: [20, 56]}
32位和64位整数 # shell中不支持
## node.js python java等高级语言的驱动中支持
64位浮点 # shell使用的全是这种类型, 如{x:3.14}
utf-8 # 字符串类型
ObjectID
Date # 如{x:new Date()}
正则 # 如{x:/uspcat/i}
javascript块代码 # 如{x:function(){}}
## 相当于存储过程
内嵌文档 # 如{x: {xx: "a"}}
二进制 # shell中不能使用
ObjectId
#
大小
12字节
显示为24个十六进制字符
# 空间换时间的思想
细节
前4字节是unix时间戳
后3字节集群machine hash
后2字节pid
后3字节inc自增计数器, 在前面都相等时全局自增
命名
#
数据库与集合名
不能是空字符串
特殊字符
' (空格) , $ / \ \0
应该全小写
小于64字节
数据库名不与保留库名相同,如
admin, local, config
集合名
db-text合法,但不能db.db-text得到,要db.getCollection("db-text").text得到
# db-text 会认为是减法
## 数据库名可以是db-text
可以a.b来命名来划分子集合
不能以system.开头命名
api
#
collection
增
save
# 不存在时插入,存在时更新
# {$ref: 'user', $id: 1} 来保存引用
insert
删
remove('id': 'bar') # 删除一条数据
#remove()删除所有数据
drop() # 删除persons collection, 不释放文件空间
dropIndexes() # 删除所有索引
改
update(finder, updater, options或upser, multi)
# $set
# {age: {$gt: 18}, $isolated : 1} $isolated事务隔离该字段到本语句执行结束, does not work with sharded clusters
findAndModify
查
findOne()
find(finder, filter)
# limit(3).skip(10).sort({name: -1, age: 1})
## sort({$natural: 1}) 固定集合排序
# explain() 返回带统计信息的文档
## 是否用到索引,耗时,需要扫描多少文件
# hint({}) 强制使用某索引查询
# null可以匹配null, 也可以匹配{$exists: false}
# 正则可以匹配自身,也可以模式字符串
count() # document的条数
aggregate
db
# 默认存在的数据库admin, config, local
sources
# 从节点中设置的源collection
help()
persons.help()
# 显示某集合的帮助
auth('username', 'pwd')
# 切换用户
addUser()
# addUser('admin', 'asdf')
# addUser('readonly', 'asdf', true)
listCommands()
shutdownServer()
eval()
# 执行
stats()
# 当前数据库的状态
## 包括名称,collection数,索引数等
createCollection()
# {'user', {capped: true, size: 100, max: 10}}
## 创建固定集合, 100字节, 文档数上限为10
## 固定集合插入快,不能删除,无_id, 有尾部游标
getCollection("persons").text
# 同db.persons
dropDatabase()
# 删除当前数据库
repairDatabase()
# 释放空间
serverStatus()
# 返回数据库的metrics 数据
serverStatus().metrics.cursor
# 返回指针信息
ensureIndex({x: 1, y: -1}, {name: 'xy'})
# 建立x的升序, y的降序联合索引
# 只使用索引的前部, 即对x的查询可以用该索引
# {"gps": '2d'} {'gps': '2dsphere'}
## 支持gps写成 [0, 0] {x: 0, y: 0} {latitude: 0, longitude: 0} 格式
# 可以索引内嵌文档
# {unique: true} 来建立唯一索引
# {dropDups: true} 将唯一索引中重复的文档都删掉
dropIndexes
system
indexes
# 保留集合,索引
namespaces
# 也包含索引信息
js
insert({_id: 'fn', value: function() {}})
# 用db.eval('fn()') 执行
runCommand()
# {'dropIndexes': 'col', 'index': 'ind'}
# 可以返回命名执行的状态信息
{buildInfo: 1}
{collStats: 'user'}
{distinct: 'user', key: a, query: {b: 0}}
{drop: 'user'}
{dropDatabase: 1}
{dropIndexes: 'user', index: 'ind'}
{getLastError: 1}
# 上次更新的作用信息
{getLastError: 1, w: 3}
# 阻塞复制,有3个节点
{isMaster: 1}
{findAndModify: 'user', query: {a: 0}, sort: {a: 1}, update: {$set: {a: 1}}}
{listCommands: 1}
{listDatabases: 1}
{ping: 1}
{renameCollection: 'user', to: 'user1'}
{repairDatabase: 1}
# 修复并压缩当前数据库
{serverStatus: 1}
# globalLock: 全局写入锁占用了多少时间
# mem: 内存映射了多少数据
# indexCounters: B树磁盘检索(misses)和内存检索(hits)的次数
# backgroundFluhing: 后台做了多少次fsync及用的时间
# opcounters: 每种主要操作的次数
# asserts: 断言的次数
{convertToCapped: 'user', size: 100}
# 转为固定集合
{fsync: 1, lock: 1}
# 缓冲写入磁盘,并加写入锁。后可以直接复制磁盘数据来备份
# db.$cmd.sys.unlock.findOne() 解锁
# db.currentOp() 查看为空时已解锁
{resync: 1}
# 从节点重新同步
{collMod: 'users', usePowerOf2Sizes: true}
# 每次增大空间总是2的倍数,适用于常写的集合
rs
isMaster
slaveOk
dcl
help # 显示帮助
show dbs # 显示所有数据库
use mydb # 选择数据库(默认为test)
## 如果没有该数据库,则创建(插入第一条数据时实际创建)
db # 显示当前数据库名
show collections # 查看当前数据库的collections
db.eval() # 执行shell语法字符串
用户管理命令
use test # 选择需要添加用户的数据库
db.addUser('name','pwd') # 第三个参数代表是否只读 true代表是 , false代表否
## db 代表本数据库,也就是test
db.system.users.find() # 查看用户列表
db.auth('name','pwd') # 用户认证,反回1代表认证成功
db.removeUser('name')
show users # 查看所有用户
# 注
权限生效需要mongod 以 -auth参数启动
admin数据库中的user是超级管理员 , 其他数据库中的user只限于本数据库
ttl(time to live)
# mongodb每1分钟检查一次数据删除
db.log_events.ensureIndex({"createdAt": 1}, {expireAfterSeconds: 3600 })
db.log_events.insert({
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "Success!"
})
# 插入的这条数据在1小时后删除
db.log_events.ensureIndex({"expireAt": 1}, {expireAfterSeconds: 0})
db.log_events.insert({
"expireAt": new Date('July 22, 2013 14:00:00'),
"logEvent": 2,
"logMessage": "Success!"
})
# 插入的这条数据在July 22, 2013 14:00:00删除
aggregate
#
mapReduce(
function() {emit(this.cust_id, this.amount);},
# map
function(key, values) {return Array.sum(values)},
# reduce
{
query: {status: 'A'},
# query
out: 'order_totals'
# output
}
)
distinct()
count()
group({
key: {a: 1},
# $keyf: function(x) {return x.category} 定义分组函数
cond: {a: {$lt: 3}}.
$reduce: function(cur, result) {result.count += cur.count},
initial: {count: 0},
finalize: function (prev) {}
})
# 返回的文档 {retval: [], count: 0, keys: 0, ok: 0}
aggregate([
{$redact: {$cond: {
if: {$eq: ['$level', 5]},
then: '$$PRUNE',
else: '$$DESCEND'
}}}
{$match: {status: 'A'}},
{$geoNear: {...}},
{$project: {name: {$toUpper: '$_id'}, _id: 0}},
{$unwind: '$sizes'},
{$group: {_id: '$state', totalPop: {$sum: '$pop'}}},
{$skip: 10},
{$limit: 5},
{$sort: {age: -1}},
{$out: 'authors'}
])
例子
o-> 得到tags数组的长度
db.users.aggregate([{
$group: {
_id: '$username',
tags_count: {$first: {$size: '$tags'}}
}
}])
db.users.aggregate([{
$project: {
tags_count: {$size: '$tags'}
}
}])
expressions
#
$and
$or
$not
$setEquals
$setIntersection
$setUnion
$setDefference
$setIsSubset
$anyElementTrue
$allElementsTrue
$cmp
$eq
$gt
$gte
$lt
$lte
$ne
$add
$subtract
$multiply
$divide
$mod
$concat
$substr
$toLower
$toUpper
$strcasecmp
$meta
$size
$map
$let
$literal
$dayOfYear
$dayOfMonth
$dayOfWeek
$year
$month
$week
$hour
$minute
$second
$millisecond
$dateToString
$cond
$ifNull
$sum
$avg
$first
$last
$max
$min
$push
$addToSet
$near
$within
$box
$center
对象
#
全局函数
printjson
connect('localhost:27017/mydb')
# 连接另一个服务器
runProgram
对象类型
cursor
hasNext()
# 立即返回前100个数据与4Mb数据的较小者。取数据时直接读缓存
next()
forEach
复制
#
复制
mongod --master --oplogSize 100
mongod --slave --source localhost:27017
# --source指定主节点
# --only 指定只复制特定的数据库
# --slavedelay 主从复制时的延时
# --fastsync 从节点是主节点快照时,加这个选项,同步速度快
# --autoresync 重新同步
# --oplogSize 主节点oplog的大小
db.sources.insert({host: 'localhost:27017'})
# 从节点设置主节点
副本集
# 没有主节点,集群自己选举主节点
# 数据太多从节点会自动停止同步
mongod --dbpath '/var/local/mongo1' --port 27017 --replSet rs0
# 三个实例replSet 名必叫 rs0
use admin
rs.initiate({
_id: 'a',
members: [{
_id: 1,
host: 'localhost1:27017'
}, {
_id: 2,
host: 'localhost1:27018'
}]
})
# 其中一台执行初始化
rs.add('localhost:27019')
rs.status()
db.getMongo().setSlaveOk()
rs.isMaster()
rs.conf()
db.getReplicationInfo()
db.printReplicationInfo()
db.printSlaveReplicationInfo()
use local
db.addUser('name', 'pwd')
# 复制认证时用
分片
#
mongods --port 3000 --configdb localhost:27017
# 多个地址用,隔开
# 每个片都就是副本集
mongo localhost:3000/admin
db.runCommand({addshard: 'localhost:27017‘, allowLocal: true})
# 在localhost上运行时, 要设allowLocal
# 'a/localhost:27017' 让mongo知道这个片所在的副本集
db.runCommand({enablesharding: 'db1'})
db.runCommand({shardcollection: 'db1.user', key: {_id: 1}})
db.printShardingStatus()
db.runCommand({removeshard: 'localhost:27017'})
shell
#
mongo 127.0.0.1:27017/admin
# 启动sell , 默认数据库为test
mongod –port 10000 –fork –logpath= logpath=/data/mongodb/log/mongodb.log -- logappend -- dbpath=/data/mongodb/data/db –config ~/.mongodb.conf
# 启动服务 -auth开启身份验证
# --rest 开启http管理,其端口号比mongo端口号大1000
## --nohttpinterface关闭http管理
# --bindip localhost 设置只能有某ip访问
# --noscripting 完全禁止服务端js执行
# --repair 启动并修复
# 不要发送SIGKILL信号关闭(kill -9), 应发送SIGINT或SIGTERM
mongod --remove
# 结束服务
// mongodb.conf
port = 5586
fork = true
logpath = mongodb.log
mongodump --host 127.0.0.1 --port 27017 --out ./dir/name
# 备份数据库
mongodump -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -o 文件存在路径
mongorestore --host 127.0.0.1 --port 27017 --directoryperdb ./dir/name
# mongorestore -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 --drop 文件存在路径
# --drop 是先删除现有的数据
mongoexport -d tank -c users -o /home/outrun/mongo
# 导出整张表
## mongoexport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 -f 字段 -q 条件导出 --csv -o 文件名
# mongoexport -d tank -c users --csv -f uid,name,sex -o tank/users.csv
## 导出表的部分字段
# mongoexport -d tank -c users -q '{uid:{$gt:1}}' -o tank/users.json
## 根据条件导出数据
mongoimport -d tank -c users --upsert tank/users.dat
# mongoimport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 --upsert --drop 文件名
## 还原整表导出的非csv文件, --upsert 表示插入或更新现有数据
# mongoimport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 --upsertFields 字段 --drop 文件名
## 还原部分字段导出的文件, --upsertFields跟upsert一样
## 如 mongoimport -d tank -c users --upsertFields uid,name,sex tank/users.dat
# mongoimport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 --type 类型 --headerline --upsert --drop 文件名
## 还原导出的csv文件
## mongoimport -d tank -c users --type csv --headerline --file tank/users.csv
mongofiles put foo.txt
# 使用gridfs
list
get foo.txt
search
# 按文件名查找
delete foo.txt
mongostat
# 实时输出mongo状态
java client
#
1.导入mongo-java-drver-2.9.3.jar
2.api
Mongo m = new Mongo("localhost", 27017);
DB db = m.getDB("mydb");
boolean auth = db.authenticate("root", "root".toCharArray());
System.out.println("身份认证" + auth);
// 获得所有数据库名
for (String s : m.getDatabaseNames()) {
System.out.println("db : " + s);
}
// 删除数据库
m.dropDatabase("my_new_db");
// 获得collection列表
Set<String> colls = db.getCollectionNames();
for (String s : colls) {
System.out.println("collection : " + s);
}
// 获得一个collection
DBCollection coll = db.getCollection("testCollection");
// 创建document(包括内嵌文档)
DBObject doc = new BasicDBObject().append("appendField", "appendField");
doc.put("name", "MongoDB");
doc.put("type", "database");
doc.put("count", 1);
DBObject info = new BasicDBObject();
info.put("x", 203);
info.put("y", 102);
doc.put("info", info);
// 插入文档
coll.insert(doc);
// 查询文档
DBObject doc2 = coll.findOne();
System.out.println(doc2);
// 统计文档数
long count = coll.getCount();
System.out.println(count);
// 用游标遍历
DBCursor cursor = coll.find();
while (cursor.hasNext()) {
DBObject object = cursor.next();
System.out.println(object);
}
// 查询
DBObject query = new BasicDBObject();
query.put("i", 71);
cursor = coll.find(query);
// 条件查询
query = new BasicDBObject();
query.put("i", new BasicDBObject("$gt", 50)); // i>50
cursor = coll.find(query);
// 创建索引
coll.createIndex(new BasicDBObject("i", 1)); // 1代表升序 , -1是降序
// 查询索引
List<DBObject> list = coll.getIndexInfo();
for (DBObject index : list) {
System.out.println("索引 : " + index);
}
类型
// 自动生成的唯一ID
ObjectId id = new ObjectId();
System.out.println(id);