MongoDB
NoSQL 数据库,使用 bson 格式(二进制的 json)存储,C/S 架构。其客户端 mongo 使用 Javascript 语法。
数据库操作
以下皆以其的 Javascript shell 为例。
查询
最简单的查询
db.test.find({name: 'test'})
常用运算符
//比较
db.test.find({value: { $gt: 0 }})
//存在性
db.test.find({phone: {$exists: true}}) //true 不能换成 1
db.test.find({name: /y/i})
db.test.find({name: {'$regex': "y"}})
db.customers.find({name: {$regex : 'acme.*corp', $options: 'i'}})
使用表达式/函数查询
db.test.find("this.name.indexOf('y') >= 0")
db.test.find({$where: function() { return this.name.indexOf('y') >= 0 }})
db.test.find(function() { return this.name.indexOf('y') >= 0 })
数组
当值为数组而查询条件不是时,只要数组中有一个匹配查询值即为匹配成功。
指定返回的字段
传递给 find() 第二个参数,指定要返回的字段为真值,或者不要的为假值。 _id 字段会一直都返回。
db.test.find({phone: {$exists: true}}, {name: 1})
更新
db.collection.update(criteria, objNew, upsert, multi)
指定第三个参数为 true ,则 documents 不存在时插入。要更新匹配的所有 documents,指定第四个参数为 true 。[2]
db.test.update(condition, {$set: {name: value}})
{$addToSet: {field: value}}
//To add many values
{$addToSet: {a: {$each: [3 , 5 , 6]}}}
更改字段名,使用 $rename 操作[3]:
db.test.update({}, {$rename: {old: 'new'}}, false, true)
$each
在版本 2.4 之前, $each 操作符[4]仅在 $addToSet 中被支持。2.4 开始支持在 $push 中被支持。前者不保证插入的顺序,而后者会保证。
删除
db.test.remove(condition)
索引
建立索引[5]:
db.things.ensureIndex({firstname: 1})
建立索引时,指定 1 为升序, -1 为降序。
要建立不重复索引,在第二个参数中指定 unique: true。如果有重复项会失败,除非同时指定 dropDups: true 来删除重复项。[6]
命令
在 mongo shell 中,使用 db.runCommand 来执行一个服务端命令。
getLastError[7]- 最后操作的状态
其它
重命名
MongoDB(2.4.5)不支持重命名数据库[8][9]。重命名数据库文件不可行,因为文件中包含数据库名的元信息,会在 repair 操作后丢失全部数据。要重命名一个数据库,只能先复制再删除(会重建索引)。
数据类型
时间
MongoDB 使用 JavaScript 中的 Date 或者自己的 ISODate 类型表示时间,精度为毫秒。[10]Python 的 datetime (精度为微秒)在向其转换时会有精度损失。
MongoDB 的所存储的时间为 UTC 时间。使用 Python 的 naive datetime 类型时,需要转成 UTC 时间。
地理位置
点临近查询示例(适用于 MongoDB 2.4 以上版本)。其中, $maxDistance 的单位是米(2.4.3 版本验证)。
>>> db.test.save({'loc': {'type': 'Point', 'coordinates': [114, 88]}})
ObjectId('51ad5b7a0580701a25bb4406')
>>> db.test.save({'loc': {'type': 'Point', 'coordinates': [114, 20]}})
ObjectId('51ad5b7a0580701a25bb4407')
# 建立需要的索引
>>> db.test.ensure_index([('loc', pymongo.GEOSPHERE)])
'loc_2dsphere'
# 这两点的距离为 313.9km
>>> db.test.find({'loc': {'$near': {'type': 'Point', 'coordinates': [117, 20]}, '$maxDistance': 350000}})
[{'_id': ObjectId('51ad5b7a0580701a25bb4407'),
'loc': {'coordinates': [114, 20], 'type': 'Point'}}]
>>> db.test.find({'loc': {'$near': {'type': 'Point', 'coordinates': [117, 20]}, '$maxDistance': 300000}})
[]
# 这两点的距离为 243.3km
>>> db.test.find({'loc': {'$near': {'type': 'Point', 'coordinates': [180, 88]}, '$maxDistance': 300000}})
[{'_id': ObjectId('51ad5b7a0580701a25bb4406'),
'loc': {'coordinates': [114, 88], 'type': 'Point'}}]
Replication
Replica Set
默认每个节点的 priority 为 1,可修改。
默认每个节点的 votes 为 1,只有获得大多数票时一个节点才可以成为 primary。修改此选项将可以在三节点的 ReplSet 中实现单一节点也可成为 primary。不建议修改。[11]
shell 中的命令:
rs.help()- 帮助
rs.initiate(config)- 初始化 ReplSet
rs.conf()- 获取配置
rs.reconfig(config)- 更新配置
rs.status()- ReplSet 的状态
master/slave
本地启动一个 master/slave 实例(启动顺序无关)[12]
mongod --master --port 27018 --dbpath data/a --fork --logpath a.log
mongod --slave --source localhost:27018 --port 27019 --dbpath data/b --fork --logpath b.log
slave 的数据将和 master 的同步,但是在 slave 本地的更改(如单独运行过)不会同步到 master(也不会消失)。
如果使用了授权,在双方的 local 数据库中添加 repl 用户即可。[13]
要将 slave 切换为 master:[14]
- 停止双方数据库进程
- 备份或者删除 slave 的 local.* 文件
- 使用 master 模式启动原 slave
shell
shell 内建有 tojson 和 printjson 两个函数。 find() 的返回值具有方法 forEach [15]:
db.person.find().forEach(printjson)
注意
32 位系统
- 数据+索引+日志最大为 2GB
- 默认日志关闭
备份
- MongoDB 的数据库可在运行时复制后给其它 MongoDB 实例使用,但是需要先使用
--repair命令修复。
内存使用
如果单台机器上部署多个 mongod,或者可用内存少于可见内存(如 lxc 等限制内存使用时),需要手动配置 storage.wiredTiger.engineConfig.cacheSizeGB 设置。[16]
据称在 OpenVZ 上,由于 OpenVZ 报告的是瞬间可用内存,导致 MongoDB 使用过多内存。
外部链接
- 官方网站
- 官方文档
- SQL to Mongo Mapping Chart - MongoDB
- mongodb-log, MongoDB python logging handler. Python centralized logging made easy.
- Learn MongoDB
- 记一次MongoDB性能问题 | 火丁笔记
- MongoDB与内存 | 火丁笔记
- Working With Stored JavaScript in MongoDB - Mike Dirolf
- 对六月六日 LeanCloud 多项服务发生中断的说明 | LeanCloud Blog, MongoDB 集群和分片相关
Web 界面
- Fang of Mongo,基于django和jQuery,似乎有些 bug。
- rockmongo,基于PHP
服务提供者
改进
参考资料
- ↑ Advanced Queries
- ↑ Updating - MongoDB
- ↑ Updating - MongoDB
- ↑ $each — MongoDB Manual
- ↑ http://www.mongodb.org/display/DOCS/Indexes
- ↑ http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes
- ↑ getLastError Command - MongoDB
- ↑ How do you rename a MongoDB database? - Stack Overflow
- ↑ [#SERVER-701] Ability to rename databases - MongoDB
- ↑ BSON Types
- ↑ Replica Sets - Voting - MongoDB
- ↑ Master Slave - MongoDB
- ↑ MongoDB – Connecting a Slave to a Master running in auth mode « My Adventures in Coding
- ↑ Master Slave - MongoDB
- ↑ http://www.mongodb.org/display/DOCS/Scripting+the+shell
- ↑ FAQ: MongoDB Diagnostics — MongoDB Manual 3.2
- ↑ MongoDB Multi-Statement Transactions: Yes We Can | Tokutek
- ↑ MongoDB + Fractal Tree Indexes = High Compression | Tokutek