mongodb基本知识

96
lawpachi
2018.01.30 14:08 字数 2136
关系型数据库

比如大家可能熟悉的MySql, Sqlite等等,它的特点是数据以表格(table)的形式储存起来的。数据库由一张张排列整齐的表格构成,就好像一个Excel表单一样,每个表格会有若干列,比如一个学生信息表,可能包含学号、姓名、性别、入学年份、高考成绩、籍贯等等。而表格的每一排,则是一个个学生的具体信息。在企业级应用和前互联网时代,关系型数据库几乎是不二选择。关系型数据库的特点是有整齐划一的组织,很方便对数据进行描述、插入、搜索。
想象有一个传统的网上服装商店吧,它的主要的数据可能是储存在一张叫products的表单里,表单可能包含这些列:商品编号(ID)、名称(Name)、商家(brand)、主目录(cate)、子目录(sub-cat)、零售价(price)、是否促销(promotion)等等。如果有一个用户想要查找所有价格低于300元的正在促销的鞋子的编号和名称,则可以执行类似于以下的SQL语句:

SELECT ID, name FROM products WHERE cate='shoes' AND price<300 and AND promotion=true;

SQL具备了强大了的深度查询能力,能满足各式各样的查询要求。而如果要对数据进行添加和删除,成本也是非常低的。这些是SQL的优势之一, 但随着互联网的兴起以及数据形式的多样化,四平八稳的SQL表单在一些领域渐渐显现出它的劣势。让我们通过一个例子来说明。考虑一个博客后台系统,如果我们用关系型数据库为每篇博客(article)建一个表单的话,这个表单大概会包括以下这些列:

ID Title Description Author Content Likes
A_1 Title1 Political Article Joe Content 1 1 2
A_2 Title2 Humorous Story Sam Content 2 5 0

这时候用SQL数据库来存储是非常方便的,但假如我们要位每篇文章添加评论功能,会发现每篇文章可能要多篇评论,而且这个数目是动态变化的,而且每篇评论还包括好几项内容:评论的人、评论的时间、以及评论内容。这时候要将这些内容都塞进上述的那个表,就显得很困难。通常的做法是为评论(comment)单独建一个表:

ID Author Time Content Article
C_1 Anna 2014-12-26 08:23 Really good articles! A_1
C_2 David 2014-12-25 09:30 I like it! A_1
ID Category Tags Content Article
T_1 Anna 2014-12-26 08:23 Really good articles! A_1
T_2 David 2014-12-25 09:30 I like it! A_1

类似地,每篇文章可能会有若干标签(tags)。标签本身又是一个表单

ID Category Tags Content Article
T_1 Anna 2014-12-26 08:23 Really good articles! A_1
T_2 David 2014-12-25 09:30 I like it! A_1

而博客的表格则要通过foreign key跟这些相关联的表格联系起来(可能还包括作者、出版社等其它表格)。这样一来,当我们做查询的时候,比如说,“找出评论数不少于3的标签为‘政治评论’的作者为Sam的文章”,就会涉及到复杂的跨表查询,需要大量使用join语句。这种跨表查询不仅降低了查询速度,而且这些语句写起来也不简单。

MongoDB数据库

如果上述博客使用MongoDB数据库的话。如何设计数据模型呢?很简单,像下面这样

_id: POST_ID
   title: TITLE_OF_POST, 
   description: POST_DESCRIPTION,
   author: POST_BY,
   tags: [TAG1, TAG2, TAG3],
   likes: TOTAL_LIKES, 
   comments: [  
      {
         user:'COMMENT_BY',
         message: TEXT,
         dateCreated: DATE_TIME,
      },
      {
         user:'COMMENT_BY',
         message: TEXT,
         dateCreated: DATE_TIME,
      }
   ]

在MongoDB里,每篇博客文章以一个文档(document)的形式保存起来,而文档内部包含了很多项目,比如title tags
等,每一个项目都是key-value
的形式,即有一个项目的名字,比如title
,以及它的值TITLE_OF_POST
。而重要的是,一个key
可以有多个values
,他们用[]
括起来。
这种“宽松”的数据存储形式非常灵活,MongoDB不限制每个key
对应的values
的数目。比如有的文章没有评论,则它的值就是一个空集,完全没有问题;有的文章评论很多,也可以无限制地插入。更灵活的是,MongoDB不要求同一个集合(collection,相当于SQL的table)里面的不同document有相同的key,比如除了上述这种文档组织,有的文档所代表的文章可能没有likes这个项目,再比如有的文章可能有更多的项目,比如可能还有dislikes等等。这些不同的文档都可以灵活地存储在同一个集合下,而且查询起来也异常简单,因为都在一个文档里,不用进行各种跨文档查询。而这种MongoDB式的存储也方便了数据的维护,对于一篇博客文章来说,所有的相关数据都在这个document里面,不用去考虑一个数据操作需要involve多少个表格。
当然,除了上述的优点,MongoDB还有不少别的优势,比如MongoDB的数据是用JSON(Javascript Object Notation)存储的(就是上面的这种key-value的形式),而几乎所有的web应用都是基于Javascript的。因此,存储的数据和应用的数据的格式是高度一致的,不需经过转换。更多的优点可以查看:[2]

mongodb和mysql基础操作区别

创建数据库
mysql:
使用 create database 语句可完成对数据库的创建, 创建命令的格式如下:
create database 数据库名 [其他选项];
例如我们需要创建一个名为 samp_db 的数据库, 在命令行下执行以下命令:
create database samp_db character set gbk;
use 数据库名;//选择所要操作的数据库
mongodb:
use tutorial // mongodb使用use如果没有数据库会自动新建
查看数据库
都为 show databases
删除数据库
DROP DATABASE test_01;
db.dropDatabase()
创建数据库表(集合)
mysql:

create table students
    (
        id int unsigned not null auto_increment primary key,
        name char(8) not null,
        sex char(4) not null,
        age tinyint unsigned not null,
        tel char(13) null default "-"
    );

mongodb:
db.createCollection('author') 不用指定数据格式,内容宽泛。但是使用Mongoose一般会约定上数据格式。
向表(集合)中插入数据
mysql:
insert语句可以用来将一行或多行数据插到数据库表中, 使用的一般形式如下:
insert [into] 表名 [(列名1, 列名2, 列名3, ...)] values (值1, 值2, 值3, ...);
其中 [] 内的内容是可选的, 例如, 要给 samp_db数据库中的 students表插入一条记录, 执行语句:
insert into students values(NULL, "王刚", "男", 20, "13811371377");
mongodb:

db.集合名称.insert(
 {
   title: 'Forrest Gump', 
   directed_by: 'Robert Zemeckis',
   stars: ['Tom Hanks', 'Robin Wright', 'Gary Sinise'],
   tags: ['drama', 'romance'],
   debut: new Date(1994,7,6,0,0),
   comments: [  
      {
         user:'user1',
         message: 'My first comment',
         dateCreated: new Date(2013,11,10,2,35),
         like: 0 
      },
   ]
}
)

插入数据之前,我们并不需要先声明集合里面有哪些项目。我们直接插入就可以了~这一点和SQL不一样,SQL必须先声明一个table里面有哪些列,而MongoDB不需要。
查询表(集合)中数据
mysql:
select 列名称 from 表名称 [查询条件];

例如要查询 students 表中所有学生的名字和年龄, 输入语句 select name, age from students; 执行结果如下:

mysql> select name, age from students;
+--------+-----+
| name   | age |
+--------+-----+
| 王刚   |  20 |
| 孙丽华 |  21 |
| 王永恒 |  23 |
| 郑俊杰 |  19 |
| 陈芳   |  22 |
| 张伟朋 |  21 |
+--------+-----+

where 关键词用于指定查询条件, 用法形式为:select 列名称 from 表名称 where 条件;
以查询所有性别为女的信息为例, 输入查询语句: select * from students where sex="女";
mongodb:
db.集合名称.find().pretty()
这里find()里面是空的,说明我们不做限制和筛选,类似于SQL没有WHERE语句一样。而pretty()输出的是经格式美化后的数据,你可以自己试试没有pretty()会怎么样。
db.movie.find({'directed_by':'David Fincher'}).pretty()
更新表(集合)中的数据
mysql:
update 表名称 set 列名称=新值 where 更新条件;
使用示例:
将id为5的手机号改为默认的"-":update students set tel=default where id=5;
将所有人的年龄增加1: update students set age=age+1;
mongodb:
db.movie.update({title:'Seven'}, {$set:{likes:134371}})
默认只会更新第一个。如果要多个同时更新,要设置{multi:true},像下面这样:
db.movie.update({}, {$inc:{likes:10}},{multi:true})
删除表(集合)中的数据
mysql:
delete from 表名称 where 删除条件;
删除id为2的行: delete from students where id=2;
删除所有年龄小于21岁的数据: delete from students where age<20;
mongodb:
db.movie.remove({'tags':'romance'})
mysql数据库操作
mongodb操作

Mongoose

Mongoose介绍和入门
Schema与Model
Schema、Model、Entity的关系

Node
Web note ad 1