一、什么是MongoDB ?
1、MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。
2、MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
3、MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
主要特点
1、MongoDB的提供了一个面向文档存储,基本的思路就是将原来“行”的概念换成更加灵活的“文档”模型。一条记录可以表示非常复杂的层次关系。
2、Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
结构如下:
3、非常容易扩展。面对数据量的不断上涨,通常有两种方案,一种是购买更好的硬件,别一种是分散数据,进行分布式的扩展,前者有着非常大的缺点,因 为硬件通常是有物理极限的,当达到极限以后,处理能力就不可能再进行扩展了。所以建议的方式是使用集群进行扩展。MongoDB所采用的面向文档的数据模 型使其可以自动在多台服务器之间分割数据。它还可以平衡集群的数据和负载,自动重排文档。
4、MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
5、丰富的功能。包括索引、存储JavaScript、聚合、固定集合、文件存储等。
6、方便的管理,除了启动数据库服务器之外,几乎没有什么必要的管理操作。管理集群只需要知道有新增加的节点,就会自动集成和配置新节点。
二、Mongodb的基本概念
不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下面我们挨个介绍。
下表将帮助您更容易理解Mongo中的一些概念:
通过下图实例,我们也可以更直观的的了解Mongo中的一些概念:
数据库
1、一个mongodb中可以建立多个数据库。
2、MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
3、数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串。
1.不能是空字符串("")。2.不得含有' '(空格)、.、$、/、\和\0 (空宇符)。3.应全部小写。4.最多64字节。
4、有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
1.admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。2.local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合 3.config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
文档
文档是mongodb中的最核心的概念,是其核心单元,我们可以将文档类比成关系型数据库中的每一行数据。
多个键及其关联的值有序的放置在一起就是文档。MongoDB使用了BSON这种结构来存储数据和网络数据交换。
BSON数据可以理解为在JSON的基础上添加了一些json中没有的数据类型。
如果我们会JSON,那么BSON我们就已经掌握了一半了,至于新添加的数据类型后面我会介绍。
文档例子如下:
{name:"张三",age:20,hobby:["看书","旅游","唱歌"]}
需要注意的是:
1. 文档中的键/值对是有序的。
2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌人的文档)。
3. MongoDB区分类型和大小写。
4. MongoDB的文档不能有重复的键。
5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
1 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
2 .和$有特别的意义,只有在特定环境下才能使用。
3 以下划线"_"开头的键是保留的(不是严格要求的)。
集合
集合就是一组文档的组合。如果将文档类比成数据库中的行,那么集合就可以类比成数据库的表。
在mongodb中的集合是无模式的,也就是说集合中存储的文档的结构可以是不同的,比如下面的两个文档可以同时存入到一个集合中:
{"name":"mengxiangyue"}{"Name":"mengxiangyue","sex":"nan"}注:当第一个文档插入时,集合就会被创建。
合法的集合名
1. 集合名不能是空字符串""。
2. 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
3. 集合名不能以"system."开头,这是为系统集合保留的前缀。
4. 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
MongoDB 数据类型
下表为MongoDB中常用的几种数据类型。
3.1 windows启动服务器端(安装完mongodb后)
- 找到mongodb安装目录,一般是 C:\Program Files\MongoDB 2.6 Standard\bin
- 按下Shift+鼠标右键,选择在此处打开命令窗口
- 在除C盘外的盘符新建一个空目录,如 D:\Mongodb\data
- 在命令行中输入mongod --dbpath=刚创建的空目录,如
mongod --dbpath=D:\Mongodb\data
- 再按回车键
- 如果出现waiting for connections on port 27017就表示启动成功,已经在27017端口上监听了客户端的请求
- 注意:--dbpath后的值表示数据库文件的存储路径,而且后面的路径必须事先创建好,必须已经存在,否则服务开启失败
- 注意:这个命令窗体绝对不能关,关闭这个窗口就相当于停止了mongodb服务
3.2 启动客户端连接服务器
- 找到mongodb安装目录,一般是 C:\Program Files\MongoDB 2.6 Standard\bin
- 按下Shift+鼠标右键,选择在此处打开命令窗口
- 命令窗体中输入 mongo --host=127.0.0.1 或者 mongo 按回车键
备注:--host后的值表示服务器的ip地址 备注: --host=127.0.0.1 表示的就是本地服务器,每次数据库都会默认连接test数据库
4. MongoDB基本概念
- 数据库 MongoDB的单个实例可以容纳多个独立的数据库,比如一个学生管理系统就可以对应一个数据库实例
- 集合 数据库是由集合组成的,一个集合用来表示一个实体,如学生集合
- 文档 集合是由文档组成的,一个文档表示一条记录,比如一位同学张三就是一个文档
----------------------------------------------------------------------
mongoose初级简单使用教程:
安装Mongoose
$
npm install mongoose
连接数据库
var
mongoose =
require
(
'mongoose'
);mongoose.connect(
'mongodb://localhost/test'
);
定义你的schema
这里的schema相当于模型,但是mongoose里面除了schma外还有一个model的概念。可以先暂时这样理解:我们首先定义schema,然后再由schema生成model,这个时候的model才拥有了与数据库交互的方法。
我们先定义一个博文的schema,如下。
var
blogSchema =
new
Schema({ title:
String
, author:
String
, body:
String
, comments: [{ body:
String
, date:
Date
}], date: {
type
:
Date
,
default
:
Date
.now }, hidden:
Boolean
, meta: { votes:
Number
, favs:
Number
}});
我们传递给mongoose的Schema构造器的对象结构中,key代表我们定义的属性名称,value则是这项属性的类型。目前mongoose允许的几种类型有:
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
这些类型中,除了Mixed、ObjectId是Schema.Types的属性外,其它都是javascript自有的属性。
定义完schema之后,我们由它生成model。
var B
log
= mongoose.model(
'Blog'
, blogSchema);
之后当我们需要初始化一条博文的记录的时候,我们就可以这样初始化:
var
blog =
new
Blog({ title:
'this is my blog title'
, author:
'me'
, body:
'the body of my blog. can you see that?'
});
数据库操作
定义完模型之后,我们就可以进行记录的增删查改了。mongoose的增删查改十分简单,以我们上一节的Blog模型为例,当我们初始化了一条博文的记录的时候,并没有将它保存进数据库中。这个时候,我们只要调用blog实例的save方法就可以将记录插入数据库中了。
blog .save ();
还可以给save方法传递一个错误回调函数,如果保存过程中发生错误将会调用该函数。
另外一种保存记录的方法是使用我们之前定义好的Blog对象,调用它的create方法:
Blog
.create
({
title
:
'another blog title'
,
author
:
'still me'
,
body
:
'the blog body again!'
},
function
(err, small) { if (err) return handleError(err);
// saved!
});
数据库中有了记录,下一步可能就是需要做查询了。例如,查询作者“me”的文章。一种方法是:
Blog
.find
({
author
:
'me'
})
.exec
(
callback
);
另一种方法是:
Blog
.find
({
author
:
'me'
},
callback
);
基本上所有涉及到查询的模型方法都有这样两种形式的查询方式,一种是不往查询方法中传递回调函数,这时查询方法不会立即执行查询,而是返回一个query对象,用户可以再在query对象上修改查询条件,直到执行exec(callback)方法;而第二种是往查询方法中传递回调函数,这时查询方法立即执行。
推荐使用前者,因为这样方便指定复杂的条件以及用于链式调用。例如我可以找出这样一篇博文:
Blog
.find
({
author
:
'me'
})
.where
(
'title'
)
.equals
(
'this is title'
)
.where
(
'meta.votes'
)
.gt
(
17
)
.lt
(
66
)
.limit
(
10
)
.sort
(
'-date'
)
.select
(
'title author body'
)
.exec
(callback);
现在我们插入了数据,并且可以查询了,接下来就是删除一些我们不需要的记录了。代码也还是比较简单:
Blog.remove({ author:
'me'
},
function
(err) {
if
(err)
return
handleError(err);
// removed!
});
最后就是更新了。在mongoose里,模型的update方法是只做更新,并不会返回对象。如果需要获取要更新的对象,要使用模型的findOneAndUpdate方法。
Blog
.update
({
author
:
'me'
}, {
title
:
'new title'
}, {
multi
: true },
function
(err, numberAffected, raw) { if (err) return handleError(err); console
.log
(
'The number of updated documents was %d'
, numberAffected); console
.log
(
'The raw response from Mongo was '
, raw);});