MongoDB: The Definitive Guide

第一章 简介

MongoDB是面向文档的数据库,不是关系型数据库。内置对MapReduce的支持,以及对地理空间索引的支持。

  • 丰富的数据模型
  • 容易扩展,它所采用的面向文档的数据模型可以使其在多台服务器之间分割数据
  • 丰富的功能,索引、存储Javascript、聚合、固定集合、文件存储
  • 不牺牲速度,尽可能地将服务器端处理逻辑交给客户端
  • 简便的管理,尽可能地让服务器自动配置

 

第二章 入门

2.1 文档

文档是MongoDB的核心概念。

  • MongoDB不但区分类型,也区分大小写。
  • 不能有重复的键。
  • 文档的键是字符串,不能含有‘\0’,这个字符用来表示键的结尾
  • .和$有特别的意义,被保留
  • 以下划线_开头的键是被保留的

2.2 集合

集合就是一组文档。

  • 在一个集合里用键标注类型,不如将不同类型分到不同的集合里,这样查询会快很多
  • 把同种类型的文档放到一个集合里,这样数据会更加集中
  • 索引是按照集合来定义的

命名:

  1. 集合名不能是空字符串“”
  2. 集合名不能含有\0字符(空字符)
  3. 集合名不能以system.开头
  4. 用户创建的集合名不能含有$

推荐使用子集合来组织数据。以“.”分开的按命名空间划分。

2.3 数据库

多个集合组成数据库。数据库通过名字来标识:

  • 不能是空字符串
  • 不得含有’’、.、$、/、\、和\0
  • 应全部小写
  • 最多64字节

保留数据库:admin、local、config

2.4 启动MongoDB

要启动该服务,需要运行mongod可执行文件。

  • 默认路径/data/db(C:\data\db);端口27017
  • 启动HTTP服务器,监听数字比主端口号高1000 。对于默认端口,就是28017,可访问http://localhost:28017 来获取数据库管理信息。

2.5 MongoDB Shell

运行mongo启动shell。(mongo [host/db: port])

  • 功能完备的Javascript解释器,可以充分利用Javascript标准库,可以定义和调用Javascript函数,可以使用多行命令。

image

MongoDB客户端,全局变量db,用use [db]命令切换数据库

基本操作

  1. 创建 db.blog.insert(post)
  2. 读取 db.blog.find() | db.blog.findOne()
  3. 更新 db.blog.update(condition, new)
  4. 删除 db.blog.remove(condition)

db.help()可以查看数据库级别的命令的帮助,集合的相关帮助可以通过db.foo.help()来查看。

image

函数名不写括号,就会显示该函数的Javascript源码。

  • 当有属性和目标集合同名时(如version),db.version不能返回正确的collection,这时可以使用getCollection函数:db.getCollection(“version”)
  • x.y和x[‘y’]完全等价,db.blog.posts也可以写作db.blog[‘posts’]
var collections = ["posts", "comments", "authors"]

for (i in collections) {
    doStuff(db.blog[collections[i]]);
}

2.6 数据类型

基本数据类型、数字、日期(new Date())、数组、内嵌文档等。

  • 尽量不要在Shell下覆盖整个文档(整数转化为浮点数)

_id和ObjectId

  • ObjectId是_id的默认类型,用12字节的存储空间

image

  • 秒级别的唯一性,大致会按照插入的顺序排列,隐含了文档创建的时间
  • _id通常由客户端驱动程序完成

 

第三章 创建、更新及删除文档

基本的插入删除修改操作

db.foo.insert({"bar":"baz"})
db.users.remove()
db.mailing.list.remove({"opt-out":true})
start = time.time()
db.drop_collection("bar")

joe.relationships={"friends":joe.friends,"enimies":joe.enimies};
delete joe.friends;
delete joe.enimies;
db.users.update({"name":"joe"}, joe)

使用修改器$set, $inc, $ne, $push, $addToSet, $each

//添加或删除键值
db.users.update({"name":"joe"}, {"$set":{"favorite book":"war and peace"}})
db.users.update({"name":"joe"}, {"$unset":{"favorite book":1}})

//增减数值
db.games.update({"game":"pinball", "user":"joe"}, {"$inc":{"score":50}})

//向数组添加值
db.papers.update({"authors cited":{"$ne":"Richie"}}, {"$push":{"authors cited":"Richie"}})

//集合中增加值,避免重复
db.users.update({"_id":ObjectId("xxxx")},{"$addToSet":{"emails":"xxx@126.com"}})
db.users.update({"_id":ObjectId("xxxx")},{"$addToSet":{"emails":{"$each":["xxx@126.com", "xxx@hotmail.com"]}}})

//集合中删除值
db.lists.insert("todo":["dishes","laundry","dry cleaning"])
db.lists.update({},{"$pull":{"todo":1}})   //从数组末尾删除
db.lists.update({},{"$pop":{"todo":-1}}) //从数组开头删除

//数组定位
db.blog.update({"post":post_id},{"$inc":{"comments.0.votes":1}})  //用下标
db.blog.update({"comments.author":"John"},{"$set":{"comments.$.author":"Jim"}}) //只替换第一个

同一套代码既创建又更新文档——upset

要是没有文档符合更新条件,就会以这个条件和更新文档为基础创建一个新的文档。如果找到了匹配的文档,则正常更新。

//update的第3个参数表示这个是upsert
db.analytics.update({"url":"/blog"}, {"$inc":{"visits":1}}, true)

save Shell帮助程序

save是一个Shell函数,可以在文档不存在时插入,存在时更新。要是文档含有_id键,save会调用upsert,否则会调用插入。

> var x = db.foo.findOne()
> x.num = 42
42
> db.foo.save(x)

更新多个文档

//要使匹配到的文档都得到更新,可以设置update的第4个参数为true
> db.users.update({birthday:"10/13/1978"},
... {$set:{gift:"Happy Birthday!"}}, false, true)

//要知道更新了多少文档
> db.runCommand({getLastError: 1})

返回已更新的文档

> ps = db.runCommand({"findAndModify":"processes",
... "query":{"status":"READY"},
... "sort":{"priority":-1},
... "update":{"$set":{"status":"RUNNING"}}).value
> doSomething(ps)
> db.processes.update({"_id":ps._id},{"$set":{"status":"DONE"}})

数据库会为每一个MongoDB数据库连接创建一个队列。

 

更多精彩内容,@https://www.mongodb.org/

posted @ 2015-07-06 19:10  维博.WILBUR  阅读(417)  评论(0编辑  收藏  举报