MongoDB入门

日期:2016-2-26 22:51 | 标签: MongoDB | 阅读:787

我买的服务器是linux,然后自己又喜欢写一写小程序,排除了工作中经常使用的sqlserver,此外,也想一窥nosql的真相,那么mongodb是不二之选!

Why Mongo

  1. 待处理的数据量很大,或者对数据访问的效率要求很高,从而必须将数据放在集群上。
  2. 想采用一种更为方便的数据交互方式来提高应用程序开发效率。
    参考链接:为什么使用NoSQL,通过这篇文章也第一次知道了阻抗失谐(虽然还是不懂)的概念。

启动

windows启动

# 本地启动
mongod --dbpath  ../blog --port 10001   --journal
# 连接服务器
mongo 127.0.0.1:27017

linux/unix启动

./mongod --dbpath  ../blog --port 10001   --journal

一对多建模

这或许是被问得最多的关于mongodb的问题了。 这里参考mongodb设计相关博文进行总结:

  1. 一对很少(不需要单独查询语句,但是无法单独查询)
    直接作为内嵌文档
  2. 一对许多(适用于一对)
    内嵌id序列
  3. 一对非常多
    为了避免文档16m大小限制,用一个文档存储主机,在每个日志文档中保存这个主机的ObjectID
  4. 多对多
    可以建立双向关联,但是更新时要同时双向操作,否则无法保证原子性

技巧

  1. 反范式化
    反范式化在节省你读的代价的同时会带来更新的代价,即更新时每次都要更新冗余字段,只有读写比较高的情况下才应该采取反范式化的设计。
  2. 双向关联
    你将无法对冗余的数据进行原子更新。

准则

  1. 优先考虑内嵌,除非有什么迫不得已的原因。
  2. 需要单独访问一个对象,那这个对象就不适合被内嵌到其他对象中。
  3. 数组不应该无限制增长。如果many端有数百个文档对象就不要去内嵌他们可以采用引用ObjectID的方案;如果有数千个文档对象,那么就不要内嵌ObjectID的数组。该采取哪些方案取决于数组的大小。
  4. 不要害怕应用层级别的join:如果索引建的正确并且通过投影条件限制返回的结果,那么应用层级别的join并不会比关系数据库中join开销大多少。
  5. 在进行反范式设计时请先确认读写比。一个几乎不更改只是读取的字段才适合冗余到其他对象中。
  6. 在mongodb中如何对你的数据建模,取决于你的应用程序如何去访问它们,数据的结构要去适应你的程序的读写场景。

设计参考

MongoDB数据库设计中6条重要的经验法则

查询

最近有用到mongoDB做数据存储,难免要用到一些复杂的查询语句,这里对这些查询做一些小小的梳理。
具体查询可以参考:mongodb查询操作使用条件查询、where子句等(转并学习)

模糊查询

简单来说,其实用的就是正则匹配,举个栗子,你要查找包含字符串 ab 的属性可以这么做:

db.user.find({"name":/ab/})

更新

举一个高级点的例子:用一个字段更新另一个字段

db.YourTable.find().forEach(
   function(item){                 
       db.YourTable.update({"_id":item._id},{"$set": {"FIELD1":item.FIELD2}},false,true) 
    }
)

upsert

没有则创建新记录

删除

# 删除"id":"12"数据
> db.sourcetable.remove({"id":"12"})

# 删除所有数据
> db.test_ttlsa_com.count()
> db.test_ttlsa_com.remove({})
> db.test_ttlsa_com.count()

# 删除集合
> show collections
> db.test_ttlsa_com.drop()
> show collections

# 删除整个数据库
> show dbs
local   0.078125GB
ttlsa_com       0.203125GB
> db
ttlsa_com
> db.ttlsa_com.getDB()
ttlsa_com
> show collections
system.indexes
> db.dropDatabase()
{ "dropped" : "ttlsa_com", "ok" : 1 }
> db
ttlsa_com
> show dbs
local   0.078125GB

索引

# 查看索引
db.table.getIndexes()
# 删除索引:方式1
db.table.dropIndex({"key" : 1})   
# 删除索引:方式2
db.table.dropIndex({"key" })   
## 删除所有
db.table.dropIndex("*")

表间备份

# 同数据库
db.source.find().forEach(function(doc) {
  db.target.insert(doc);
});
# 不同数据库
use db_source;
var docs = db_source.collection_souce.find();
use db_target;
docs.forEach(function(d){db.collection_target.insert(d)});
# 不同实例
mongodump -h host:port -d db_source -c collection_source  
mongorestore -h host:port -d db_target -c collection_target dump/collection_source.bson

参考: https://docs.mongodb.com/manual/reference/program/mongodump/

数据备份

  1. 首先得在需要备份的库下创建一个用户(必须要有一个,admin不行),
    db.createUser({user:'pengyi_blog',pwd:'YOURPWD',roles:["readWrite","dbAdmin"]})
    
  2. 在本地mongodb/bin下运行以下命令
    mongodump  -h YOURIP -u "YOURUSERNAME" -p "YOURPWD" -d DBNAME -o PATH
    
  3. 还原[暂未试验]
    参考链接: MongoDB数据备份与恢复

报错

  1. I CONTROL Hotfix kb2731284 or a later update is not installed, will zero-out files.
    解决办法:在数据中目录下删掉mongod.lock,然后就没问题了,但是不知道为什么?
  2. mongodb error(MongoError: E11000 duplicate key error index)
    解决办法:将数据库清空一下,或者将对应的collection删除就可以了(删掉所有的值还是无法解决问题),原因是索引表里记录没有删除。
  3. 连接池爆满,把网站关掉后恢复正常,查看最大连接池居然是52317,当前已使用111,明显有点不正常。云数据库MongoDB为什么需要限制连接数?
  4. Invalid path. Must be either string or array mongoose, 都是 versionKey 惹的祸

    https://stackoverflow.com/questions/30445012/invalid-path-must-be-either-string-or-array-mongoose

参考

版权声明: 署名-非商业性使用-禁止演绎 4.0 国际(CC BY-NC-ND 4.0
Copyright ©2013-2017 | 粤ICP备14081691号 | yipeng手工打造 | 联系方式