MongoDB学习笔记(一)

1.MongoDB简介

 

MongoDB介绍

MongoDB是面向文档的非关系型数据库,不是如今使用最广泛的关系型数据库,其放弃关系模型的缘由就是为了得到更加方便的扩展、稳定容错等特性。面向文档的基本思路就是:将关系模型中的“行”的概念换成“文档(document)”模型。面向文档的模型能够将文档和数组内嵌到文档中。所以,实际中能够用一条数据表示很是复杂的结构。
MongoDB没有预约义模式:文档的键(key)和值(value)再也不是固定的类型和大小,并且根据需求要添加或者删除字段变得更容易了。因为没有模式须要更改,一般不须要迁移大量数据。没必要将全部数据都放到一个模子里面,应用层能够处理新增或丢失的键。这样开发者能够很是容易地变动数据模型。
实际应用中,随着数据量的增大,数据库都要进行扩展。扩展有纵向扩展和横向扩展。纵向扩展是使用计算能力更强的机器,也是最省力的方法,可是很容易达到物理极限,不管花多少钱也买不到最新的机器了。横向扩展就是经过分区将数据分散到更多的机器上。MongoDB的设计采用横向扩展。面向文档的数据模型使它很容易地在多台服务器之间进行数据分割。还能够自动处理跨集群的数据和负载,自动从新分配文档,以及将用户请求路由到正确的机器上。开发者根本不用考虑数据库层次的扩展问题,须要扩展数据库时,在集群中添加机器便可,MongoDB会自动处理后续的事情。
MongoDB有如上各类特性,但为了达到这些,他也放弃了关系型数据库的某些功能如表链接join和复杂的多行事务。

2017-05-12_214955.png-8kB 
直观了解: 
2017-05-17_165633.png-13kBjava

 

MongoDB的优点与劣势

 

优点

  1. 快速!基于内存,将热数据存放在物理内存中(不只仅只是索引和少部分数据),从而提升了总体速度和效率。
  2. 高扩展性!MongoDB的高可用和集群架构拥有十分高的扩展性。
  3. 自身的FailOver机制!在副本集中,当主库遇到问题,没法继续提供服务的时候,副本集将选举一个新的主库继续提供服务。
  4. JSon格式的数据!MongoDB的Bson和JSon格式的数据十分适合文档格式的存储与查询。
 

劣势

  1. 应用经验少!因为NoSQL兴起时间短,应用经验相比关系型数据库较少。
  2. 因为以往用到的都是关系型数据库,可能会形成使用者一开始的不适应。
  3. 无事务机制!MongoDB自己没有自带事务机制,若须要在MongoDB中实现事务机制,需经过一个额外的表,从逻辑上自行实现事务。

 

2.MongoDB与MYSQL对比

数据库 MongoDB MySQL
数据库模型 非关系型 关系型
存储方式 以类JSON的文档的格式存储 不一样引擎有不一样的存储方式
查询语句 MongoDB查询方式(相似JavaScript的函数) SQL语句
数据处理方式 基于内存,将热数据存放在物理内存中,从而达到高速读写 不一样引擎有本身的特色
成熟度 新兴数据库,成熟度较低 成熟度高
普遍度 NoSQL数据库中,比较完善且开源,使用人数在不断增加 开源数据库,市场份额不断增加
事务性 仅支持单文档事务操做,弱一致性 支持事务操做
占用空间 占用空间大 占用空间小
join操做 MongoDB没有join MySQL支持join

下面是Mongodb与Mysql的操做命令的对比: 
2017-05-05_102256.png-15kBmysql


 

MongoDB基础知识与CRUD

1.文档(document):至关于传统关系型数据库的“行”,但比传统行表示的信息更加复杂。例如:正则表达式

 
{"name":"jack","age":18,"sex":"male"}

2.集合(collection):这个在MongoDB中表明一组文档,相似于关系型数据库中的表。但在MongoDB中的表(就是集合)是没有模式的,你能够将彻底不一样的文档放入同一个集合中.但在实际使用中,为特定集合隐性规定一种模式。注:当集合里没有任何文档时集合其实也是不存在的。当第一个文档插入时,集合就会被建立。 
3.数据库(database):在MongoDB中,一组集合能够组成一个数据库。一个MongoDB实例能够承载多个数据库。每一个数据库都有独立的权限控制。在实际应用中,一般,一个应用的全部数据放置在一个数据库中。 
4.数据类型:MongoDB中的文档相似于JSON。JSON是一种简单的数据交换格式,在数据类型方面,只支持:null,布尔,数字,字符串,数组和对象。这几种类型在某些实际应用中表现力仍是不够,好比JSON自己不直接支持日期类型,对于数字,JSON自己也无法区分整数和浮点数,更不能区分32位数字和64位数字。为此,MongoDB再保留了JSON的各种特性外,又为其添加了一些数据类型。 
1.null:用于表示空值或不存在的字段。Shell中这样表示:{"x":null} 
2.布尔:有两个值,true和false。Shell中这样使用:{"x":true} 
3.数字:Shell中数字均为64位浮点数,如在Shell中{"x":3.14}{"x":3}这两个文档中的值均是64位的浮点数。 
4.字符串:这个用的最广,Shell中这样表示:{"x":"hello world!"} 
5.日期:这个在数据存储时,存储的是从标准纪元开始的毫秒数,没有存储时区信息。 
6.正则表达式:文档中能够包含正则表达式,采用JavaScript的正则表达式语法便可,Shell中这样表示:{"x":/foobar/i}
7.数组:数组是一组值,既能够表示为有序对象(列表,栈,队列等)也能够表示无序对象(集合),Shell中这样表示一个数组:{"things":["pie",3.14]}。 
8.内嵌文档:把一个文档整个做为另外一个文档某一个键对应的值。 
其余包括二进制数据,代码等。sql

 

MongoDB入门(Shell基本操做)

运行mongo启动shell: 
2017-05-05_154321.png-3.8kB 
shell是一个功能完备的JavaScript解释器,可运行任意的JavaScript程序。这里不作示例。 
MongoDB的默认数据库为"db",该数据库存储在data目录中。 
1.选择数据库mongodb

#选择名test数据库
use tset

  

2017-05-05_154819.png-1.6kB 
若是忘记了数据库名称能够输入以下代码查询全部数据库名称:"show dbs" 命令能够显示全部数据的列表shell

 
show dbs

  

2017-05-05_154952.png-2.7kB 
查看数据库中的集合名:数据库

 
show collections

  

结果如图所示: 
2017-05-05_161235.png-2kB 
下表列出了 RDBMS 与 MongoDB 对应的术语: 
2017-05-17_170031.png-4.5kBjson

 

插入文档

insert函数可将一个文档插入到集合中去。以一个博客举例。先建立一个叫post的变量(JavaScript对象)有三个键和对应的属性。插入代码:数组

 
db.blog.insert(post)

如图所示: 
2017-05-05_161551.png-6kB 
批量插入bash

 
db.blog.insertMany([{"_id":0},{"_id":1},{"_id":2}])

  

2017-05-05_171812.png-3.5kB

 

查询文档

查询代码以下:

 
db.blog.find()

如图所示: 
2017-05-05_161943.png-5kB 
多出来的"_id"就是MongoDB自动建立的默认为ObjectID类型的对象。在一个集合里,每一个文档都由惟一的"_id",确保集合中的每一个文档都能被惟一标识,它采用12字节的存储空间,由24个16进制数字组成,可分为四部分组成:

{0,1,2,3} {4,5,6} {7,8} {9,10,11}
时间戳 机器码 PID(线程码) 自增计数器

若是插入文档时没有"_id"键,系统会为咱们自动建立一个。 
若只想查看一个文档,能够用findOne:

db.blog.findOne()

  

查询具体的某一个文档那么就要以json的形式添加查询条件,例如:

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

  

以上实例中相似于 WHERE 语句:WHERE title = 'My Blog Post';

2017-05-05_162233.png-7.7kB

 

修改文档

若是给博客新增一个评论功能,则须要新增key-value,用于保存评论数组。

 
post.comments = []

以后用新版本的文档替换旧版本:

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

2017-05-05_162757.png-7.3kB

使用修改器:

"$Set":用来指定一个字段的值,若字段不存在,则建立它。
db.users.update({"sex":"male"},{"$Set":{"gift":"happy birthday!"}})
/*这样只会更新一个文档,若要更新多个文档,则须要将update的第四个参数设置为true*/
db.users.update({"sex":"male"},{"$Set":{"gift":"happy birthday!"}},false,true) 
"$inc":用来增长已有键的值,若键不存在,就建立它。(与"$Set"相似,专门用来增长数字的,只能用于整形,长整型,双精度浮点型)
db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}}) 
"$push":会向已有的数组末尾加入一个元素,若数组不存在,则建立数组。与"$each"自操做符一同使用能够一次添加多个值。
db.stock.ticker.update({"_id":"1"},{"$push":{"hourly":{"$each":[562.667,562.790,562.123]}}}) 
"$addToSet":能够避免重复插入。若数组内已有相同数据,则不差入。与"$each"自操做符一同使用能够一次添加多个值。
db.users.update({"_id""1},{"$addToSet":{"emails":"joe@gmail.com"}})
"$push":删除数组里的元素.("$pop":将数组当作队列或栈,从两端删除。"$pull":将所匹配到的数组中的值删除,而不是只删除一个)

删除文档

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

2017-05-05_162941.png-2.9kB 
删除整个集合用drop()

 
db.blog.drop()

索引

MongoDB使用 ensureIndex() 方法来建立索引。

db.COLLECTION_NAME.ensureIndex({KEY:1})

语法中 Key 值为你要建立的索引字段,1为指定按升序建立索引,若是你想按降序来建立索引指定为-1便可。 
固然也能够给多个字段创建索引

db.col.ensureIndex({"title":1,"description":-1})

管道聚合

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操做是能够重复的。 
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。 
这里咱们介绍一下聚合框架中经常使用的几个操做:

  • $project:修改输入文档的结构。能够用来重命名、增长或删除域,也能够用于建立计算结果以及嵌套文档。
 
db.article.aggregate(
{ $project : {
title : 1 ,
author : 1 ,
}}
);
  • $match:用于过滤数据,只输出符合条件的文档。
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
  • $limit:用来限制MongoDB聚合管道返回的文档数。
db.article.find().limit
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
db.article.aggregate( { $skip : 5 });
  • $group:将集合中的文档分组,可用于统计结果。

  • $sort:将输入文档排序后输出。


 

Java操做MongoDB

 

链接数据库

链接数据库,你须要指定数据库名称,若是指定的数据库不存在,mongo会自动建立数据库。 
所需jar包: mongo-java-driver-3.2.2.jar 
链接数据库的Java代码以下:

 1 import com.mongodb.MongoClient;
 2 import com.mongodb.client.MongoDatabase;
 3 public class MongoDBJDBC{
 4 public static void main( String args[] ){
 5 try{
 6 // 链接到 mongodb 服务
 7 MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
 8 // 链接到数据库
 9 MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
10 System.out.println("Connect to database successfully");
11 }catch(Exception e){
12 System.err.println( e.getClass().getName() + ": " + e.getMessage() );
13 }
14 }
15 }

 

建立集合: 
咱们可使用 com.mongodb.client.MongoDatabase 类中的createCollection()来建立集合 
代码片断以下:

 
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
public class MongoDBJDBC{
public static void main( String args[] ){
try{
// 链接到 mongodb 服务
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// 链接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
System.out.println("Connect to database successfully");
mongoDatabase.createCollection("test");
System.out.println("集合建立成功");
}catch(Exception e){
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}
}
}

 

 

插入文档

 
//插入文档
/**
* 1. 建立文档 org.bson.Document 参数为key-value的格式
* 2. 建立文档集合List<Document>
* 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>) 插入单个文档能够用 mongoCollection.insertOne(Document)
* */
Document document = new Document("title", "MongoDB").
append("description", "database").
append("likes", 100).
append("by", "Fly");
List<Document> documents = new ArrayList<Document>();
documents.add(document);
collection.insertMany(documents);
System.out.println("文档插入成功");

 

 

查询文档

 
//检索全部文档
/**
* 1. 获取迭代器FindIterable<Document>
* 2. 获取游标MongoCursor<Document>
* 3. 经过游标遍历检索出的文档集合
* */
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}

 

 

修改文档

 
//更新文档 将文档中likes=100的文档修改成likes=200
collection.updateMany(Filters.eq("likes", 100), new Document("$set",new Document("likes",200)));
//检索查看结果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}

 

 

删除文档

 
//删除符合条件的第一个文档
collection.deleteOne(Filters.eq("likes", 200));
//删除全部符合条件的文档
collection.deleteMany (Filters.eq("likes", 200));
//检索查看结果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}
相关文章
相关标签/搜索