MongoDB(二):基础知识

MongoDB的基本概念

  1. 文档是MongoDB中数据的基本单元,非常类似于关系型数据库管理中的行,但更具表现力。

  2. 集合可以看作是一个拥有动态模式的表。

  3. MongoDB的一个实例可以拥有相互独立的数据库,每个数据库都拥有自己的集合。

  4. 每个文档都有一个特殊的键_id,这个键在文档所属的集合中是唯一的。

  5. MongoDB自带了一个简单但功能强大的JavaScript shell,可用于管理MongoDB的实例或者数据操作。

文档

  1. 文档是MongoDB的核心概念。文档就是键值对的一个有序集。例如在 JavaScript 里面,文档就被表示为对象:

{"greeting": "Hello,World!"}

但是大多数的文档会被这个简单的例子复杂的多,通常会表现为多个键/值对:

{"greeting": "Hello,World!", "foo": 3}

从上面的例子可以看书,文档值可以是多种不同的数据类型。

文档的键是字符串,除了少数的例外情况。键可以使用任意 UTF-8 字符。

  • 键不能含有\0(空字符),这个字符用于表示键的结尾。

  • .$具有特殊的意义,只能在特定的环境下使用。

而且MongoDB不但区分类型,而且区分大小写,下面的每组的两个文档都是不同的:

{"foo": 3}
{"foo": "3"}
{"foo": 3}
{"Foo": 3}

还有一个重要的事情需要注意,就是MongoDB的文档不能有重复的键,例如下面的就是违法的:

{"greenting": "Hello, World!", "greenting": "Hello, MongoDB!"}

集合

动态模式

集合是动态模式的,所以任何文档都可以存在同一个集合里面:

{"greenting": "Hello, World!"}
{"foo": 5}

既然集合里面可以放置任何文档,随之而来的一个问题就是,还有必要使用多个集合吗:

  • 各种各样的文档放到一个集合里面,对于开发者和管理员来说不方便管理。

  • 在一个集合里面查询特定类型的文档在速度上不划算,分开查询速度则快得多。

  • 把同种类型的集合放到一个集合里面,数据会更加集中。

  • 创建索引时,因为一个集合中只放入一种类型的文档,可以更加有效的对集合进行索引。

命名

集合名需要时满足下列条件的任意UTF-8字符串:

  • 集合名不能是空字符串(””)

  • 集合名不能包含\0字符

  • 集合名不能以system.开头

  • 集合名中不能包含保留字符$

数据库

在MongoDB中,多个文档组成集合,多个集合可以组成数据库。
数据库名必须是满足以下条件的UTF-8字符:

  • 不能是空字符串(“”)

  • 数据库名应该区分大小写,即便是在不区分大小写的系统也是如此。简单起见,数据库名应该全部小写。

  • 数据库名最多应为64字节。

因为数据库最终会变为文件系统里的文件,而数据库名则就是相应的文件名。这也是数据库名有这么多限制的原因。
但是一些数据库的名字是保留的,比如adminlocalconfig

启动MongoDB服务器

service mongod start

默认情况下,MongoDB的监听端口默认是27017。

启动Mongo客户端

mongo

但是这个你要确保你的恶服务器已经启动了。这样就会自动进行连接MongoDB服务器了。
这个 shell 工具其实是一个功能完备的 JavaScript 解释器。可以运行任意的 JS 程序。

基础命令

db # 查看当前选择的数据库
show dbs # 查看当前服务器的数据库列表
use footer # 选择数据库

当选定数据库之后,系统会将数据库连接赋值给全局变量db。这个变量就是通过 shell 访问 MongoDB 的主要入口点。
例如,通过db.baz可返回当前数据库的baz集合。

基本操作

创建

post = {"title": "My Blog Post", "content": "Here's my blog post.", "data": new Date()}
db.blog.insert(post)

这个插入的数据是一个 JavaScript 对象。它有这么几个键:titlecontentdate。在查询的时候,我们会看到有一个额外的_id,这个会在下面进行解释。

查找

查找多个文档

db.blog.find()

查找单个文档

db.blog.findOne()

findfindOne都接受一个查询文档作为限定条件。使用find的时候,shell会自动显示最多20个匹配的文档。

更新

例如:给先前的数据增加一个comments键:

post.comment = []
db.blog.update({"title": "My Blog Post"}, post)

update至少接受两个参数,第一个参数是限定条件,用于匹配要更新的文档。第二个是要更新的文档。
然后我们在db.blog.find()就可以看到新的键

删除

使用remove()方法可以将文档从数据库中永久删除。但是如果没有指定任何条件,那么则会删除集合内的所有文档。也可以接受一个限定条件作为参数:

db.blog.remove({"title": "My Blog Post"})

现在集合又是空的了。

_idObejctId

MongoDB中存储的数据必须有一个_id键。这个键的值可以是任何类型的。默认是一个 Object 对象。在一个集合里面,每个文档都有一个唯一的_id,类似MySQL的自增ID。

ObejctId

在设计MongoDB的时候,初衷就是用作分布式数据库,所以能够在分片的环境中生成唯一的标识符就非常的重要。
ObejctId使用12字节的存储空间,是一个由24个十六进制数字组成的字符串。
ObjectId的12字节,按照如下方式生成:

  • 前4个字节是从标准纪元开始的时间戳,单位为秒。因为使用的是当前时间,所以很担心是否要对服务器进行时钟同步。这确实是一个好主意。但是时间戳的实际值并不重要,因为只要它总是不停的增加就好了。

  • 接下来的3个字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样可以确保不同主机生成不同的ObjectId。不产生冲突。

  • 接下来的两个字节来自产生ObjectId的进程的进程标识符(PID)。

  • 前9个字节保证了同一秒钟不同机器不同进程产生的ObjectId是唯一的。最后3字节是一个自动增加的计数器。确保相同进程同一秒产生的ObjectId也是不一样的。

自动生成_id

如果插入文档时没有_id键,系统会帮你自动创建一个。可以由服务器来做这种事情。但是通过会在客户端由驱动程序完成。这样则减轻了数据库扩展的负担。

使用MongoDB shell

使用下面的方式连接到其他的任何MongoDB实例

mongo host:port/db

这样就连接到host(IP地址),端口是port上的db(此处可以更换为你要连接的数据库)了。

这样启用之后,就不会连接到任何数据库

mongo --nodb

在启动之后,可以使用new Mongo(hostname)命令来选择想要连接到的Mongod了。

conn = new Mongo(host:port)
db = conn.getDB('db')

执行这些命令之后,就可以像平常一样使用db了。

我们可以通过下面的功能来查看帮助手册

help

如果想要知道一个函数是做什么用的,可以直接在shell中输入函数名,但是不要加括号

db.foo.update

使用shell执行脚本

比如:

mongo script1.js script2.js script3.js

亦或者:

mongo --quiet host:port/db script1.js script2.js script3.js

--quiet 命令则是让mongo不要打印”MongoDB shell version ……”的提示了。

或者在交互式shell中运行脚本

load("script1.js")

然而在脚本中,shell辅助函数则是不能使用的。所以我们需要使用辅助函数对应的JS函数:

辅助函数等价函数
use foodb.getSisterDB(“foo”)
show dbsdb.getMongo().getDBs()
show collectionsdb.getCollectionNames()

创建.mongorc.js文件

这个文件会在启动 shell 时自动运行。一般来说创建此脚本的作用是创建一些自己需要的全局变量,或者为太长的名字创建比较比较短的别名,或者重写内置函数,最常见则是移除一些比较“危险”的 shell 内置函数。注意这种方法不能保护数据库免受恶意用户的攻击,只能预防自己的手误。启动 mongo时指定--norc参数,就可以禁止加载.mongorc.js

var no = function(){
    print("Not on my watch");
};
db.dropDatabase = DB.prototype.dropDatabase = no; //禁止删除数据库
DBCollection.prototype.drop = no; //禁止删除集合
DBCollection.prototype.dropIndex = no; //禁止删除索引

当需要编辑大块的代码或者对象的时候,我们可以指定编辑器,然后我们可以在编辑器内进行编辑:

// .mongorc.js
EDITOR = "/usr/bin/vim";

比如在 mongo shell 中:

>var wap = db.books.findOne({title: "War and Peace"})
>edit wap

修改完成之后,保存并退出编辑器。变量就会重新解析然后加载回 shell。

    原文作者:魔王卷子
    原文地址: https://segmentfault.com/a/1190000005728926
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞