MongoDB入门

一、基本概念解释

二、MongoDB 数据类型

下表为MongoDB中常用的几种数据类型。

ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:

前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间早了 8 个小时

接下来的 3 个字节是机器标识码

紧接的两个字节由进程 id 组成 PID

最后三个字节是随机数

MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象

由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:

> var newObject = ObjectId()

> newObject.getTimestamp()

ISODate("2018-07-05T07:21:10Z")

ObjectId 转为字符串

> newObject.str

5a1919e63df83ce79df8b38f

三、Mongodb入门命令

3.1、基本查看命令

show dbs 查看所有的数据库

use databaseName 使用某个数据库  例如:use edu

show tables/collections 查看当前库下的所有collection

3.2、库和集合的操作

查看当前所处的数据库

db

3.3、在mongodb中,库是隐式创建的,你可以use 一个不存在的库,然后在该库下创建collection,即可创建库。

db.dropDatabase(); 删除database, 把当前所用的库给删除了 , 即使里面有数据也会删除

db.createCollection(‘collectionName’), 创建collection,collection也是允许隐式创建的

db.collectionName.insert(document); 在集合(表)中插入具体数据的时候会自动创建

db.collectionName.drop() , 删除collection

举例如下:

use edu #创建数据库:edu

db.createCollection('video') #创建集合(表):video

db.video.insert({play_url:'http://www.sohu.com/a.mp4',title:'战狼2',area:'中国'})   #插入一条数据

db.video.drop()   #删除集合video

四、Mongodb基本增删改查

4.1、增加数据

mongodb存储的是文档,文档是json格式的对象,我们向数据库存储数据的时候可以使用insert方法,数据格式要以js对象格式进行存储:

语法: db.collectionName.insert(document);

db.createCollection('student')

db.student.insert({name:'zhangsan',age:'20'})  向当前students表里插入数据

4.1.1、增加单篇文档

语法: db.student.insert({title:"nice day"});

4.1.2、增加单个文档,并且指定_ID

语法: db.student.insert({_id:8,age:78,name:"lisi"});

_id 是我们在插入数据的时候,mongodb自动给文档添加的一个属性,如果我们不需要系统分配_id ,可以在添加数据的时候手动设置,覆盖原有_id ,虽然_id 的类型可以自由指定,但是在同一个集合当中必须唯一,如果插入重复的值,系统会抛出异常.

这个_id 的名称是固定的,它可以是Mongodb支持的任何数据类型,默认是ObjectId,在关系型数据库中,主键通常是数值型的,并且可以设置自增,而Mongodb的主键,原生不支持自增主键。

4.1.3、增加多个文档

db.student.insert( [{time:'friday',value:'mongodb'},{_id:1,gender:'male',name:'QQ'}])

可以以数组的方式,一次性向集合插入多个数据;同时应该注意的是,由于mongodb采用的是 J a v a S c r ip t S he l l,所以我们可以根据js特性,将文档作为值赋给变量然后进行操作:

j = {name : 'isi'};

t = {name : 'wangwu'};

db.student.insert([j,t]);

4.1.4、SAVE和INSERT的区别

save和insert都可以进行数据的插入和增加,但是也有一些异同:

对于已存在数据 { _id:1, "name":"n1" },再次进行插入操作时,

a、insert({_id:1, "name" :"n2"}) 会报主键重复的错误提示;

b、save({ _id:1, " name ":"n2"}) 会把 n1 修改为 n2 。

相同点: 若新增的数据中没有主键时,会增加一条记录。

不同点: 主键_id已存在时 :insert 会报错,save会修改当前_id的数据

即:insert有则报错,无则插入;save有则修改,无则插入

4.2、查询操作

4.2.1、FIND()

无条件的普通查询方式很简单,可以直接使用

db.collectionName.find( ) ; 一次可以查出指定集合中的所有数据

db.student.find();

按照条件进行查询操作

语法: db.collection.find( 查询表达式 , 查询的列 ) ;

例1: db.student.find({},{name:1})  //查询student集合中的name属性 (_id属性默认总是查出来)

例2: db.student.find({},{name:1, _id:0}) //查询student集合中的name属性,且不查询_id属性此处的0表示的是false,不查询

例3: db.student.find({age:20},{name:1,_id:0 } ) ;//查询student集合中age属性值为20的name属性

4.2.2、FINDONE()

findOne()和find()函数一样,只是findOne()返回的是查询结果中的第一条数据,或者返回null.

4.3、删除操作

语法: db.collectionName.remove( 查询表达式 , 选项 );

选项是指 { justOne:true/false},是否只删一行, 默认为false 注意

1: 查询表达式依然是个json对象

2: 查询表达式匹配的行,将被删掉.

3: 如果查询表达式为空对象{},collections中的所有文档将被删掉.

例1: db.student.remove({name:'n1'});//删除stu表中name属性值为'n1'的文档

例2: db.student.remove({gender:'m'},true);//删除stu表中gender属性为m的文档,只删除1行.

4.4、修改操作

语法: db.collection.update( 查询表达式 , 新值 , 选项 );

*改哪几行? --- 查询表达式

*改成什么样? -- 新值 或 赋值表达式

*操作选项 ----- 可选参数

upsert:如果要更新的那条记录没有找到,是否插入一条新纪录,默认为false

multi  :是否更新满足条件的多条的记录,默认为false

multi :是否更新满足条件的多条的记录,false:只更新第一条,true:更新多条,默认为false

例:db.student.update({name:'QQ'},{name:'MSN'}); //是指选中student表中,name值为QQ的文档,并把其文档值改为{name:"MSN"},

结果:文档中的其他列也不见了,改后只有_id和name列了。即是新文档直接覆盖了旧文档,而不是修改。

4.4.1、修改操作中的关键字

如果是想修改文档的某列,可以用$set关键字

例:db.student.update(query,{$set:{name:’QQ’}})

修改时的赋值表达式

$set 修改某列的值

$unset 删除某个列

$inc 增长某个列

$rename 重新命名某列

$setOnInsert 当upsert为true时,并且发生了insert操作时,可以补充的字段.

$INC实例

按照指定的步长增长某个列;

db.student.insert({"uid":"201203","type":"1",size:10})

db.student.update({"uid" :"201203"},{"$inc":{"size"  :  2}})

$UNSET实例

db.student.find({_id:8})

db.student.update({_id:8},{$unset:{age:'sss'}})

4.5 查询表达式

我们无论在修改删除还是查询的过程中,都需要传入查询表达式对目标数据进行查询,表达式有很多种

1:  最简单的查询表达式

{filed:value}  ,是指查询field列的值为value的文档

2:  $ne:!=

{field:{$ne:value}} 

db.stu.find({age:{$ne:16}}) 作用--查age列的值 不等于16的文档

3:$gt:大于

$lt:小于

$gte:大于或等于

$lte:小于或等于

4:  $in:[]    查询某列的值在范围内的文档

db.goods.find({cat_id:{$in:[2,8]}}

5:  $nin:not  in      查询某列不在范围内的文档

$nin:[2,3,5]

6:  $exists

语法:  {field:{$exists:1}}

作用:  查询出含有field字段的文档

7:用正则表达式查询  以”诺基亚”开头的商品

例:db.goods.find({goods_name:/诺基亚.*/},{goods_name:1});

五 游标操作

通俗的说,游标不是查询结果,而是查询的返回资源,或者接口,通过这个接口,你可以逐条对数据进行读取;

声明游标 :

var  cursor  =  db.collectioName.find(query,projection);

cursor.hasNext()  //判断游标是否已经取到尽头 

cursor.next()  //取出游标的下1个单元

用while来循环游标

var  mycursor  =  db.bar.find({_id:{$lte:5}})

while(mycursor.hasNext())  { printjson(mycursor.next());}

游标还有一个迭代函数,允许我们自定义回调函数来逐个处理每个单元.

cursor.forEach(回调函数);

var  gettitle  =  function(obj)  {print(obj.goods_name)}

var  cursor  =  db.goods.find();

cursor.forEach(gettitle);

游标在分页中的应用

比如查到10000行,跳过100页,取10行,一般地,我们假设每页N行, 当前是page页, 就需要跳过前 (page-1)*N 行, 再取N行.

在mongo中,分页是用skip(), limit()函数来实现的

//查询结果中,跳过前9995行

var  mycursor  =  db.bar.find().skip(9995);

//查询第901页,每页10条

则是  var  mytcursor  =  db.bar.find().skip(9000).limit(10);

六 group分组

mongodb支持聚合运算;

在goods表中插入数据

db.goods.insert([

{'_id':3,'cat_id':6,'price':29},

{'_id':4,'cat_id':7,'price':30},

{'_id':5,'cat_id':6,'price':31},

{'_id':6,'cat_id':7,'price':32},

{'_id':7,'cat_id':7,'price':28},

])

如果我们所处的是mysql数据库,我们可以这样查询每个类下面的商品平均价格

select  avg(price)  from  goods  group  by  cat_id;

但如果在mongodb下,我们如何查询分组内的平均值呢? 我们需要使用mongodb的聚合运算 https://docs.mongodb.com/manual/aggregation/

db.goods.aggregate([

{$match:{}},

{$group:{_id:"$cat_id",avg:{$avg:'$price'}}}

]);

其中,$match表示匹配的条件,$group表示分组的条件,$avg表示求平均值. 当然,指令还有很多,我们还可以使用limit,sort等操作

db.goods.aggregate([

{$match:{}},

{$group:{_id:"$cat_id",avg:{$avg:'$price'}}},

{$limit:1}

]);

按照价格降序排列

db.goods.aggregate([

{$match:{}},

{$sort:{price:-1}}

]);

七 MapReduce

7.1、MapReduce原理

随着大数据兴起,MapReduce的概念也越来越火,通常的概念是用于大规模数据集(1TB)的并行运算,实际上就是传统关系型数据库的group概念的延伸.

MapReduce之所以能够流行,是因为数据的大,当数据过大的时候,单个服务器无法承载,facebook,微软等等的数据中心都是分布在世界各地的, 我们所需 要的数据很可能分布在不同的服务器甚至世界各地.在这时候,我们就无法使用group操作了.

MapReduce通俗的讲,最大的优点就是可以支持分布式的group

而MapReduce的操作即分为map和reduce两步;

map ---> 映 射

reduce ---> 减少,规约,回归

7.2、MapReduce统计价格

//按照cat_id  分配  price,把price数据映射到一个数组上 var  map  =  function(){

emit(this.cat_id  ,  this.price)

}

//将映射好的数组进行操作

var  reduce  =  function(cat_id,number){ return  Array.avg(number)

}

//将统计的数据映射到res表当中db.goods.mapReduce(map,reduce,{out:'res'})

接下来我们使用mapReduce功能实现地震数据的统计

7.3、下载并导入地震信息

在国家地震科学数据共享中心下载过去一年的地震数据 http://data.earthquake.cn/sjfw/index.html?PAGEID=datasourcelist&dt=40280d0453e414e40153e44861dd0003

将数据保存为csv格式,导入到mongodb数据库中,使用mongoimport

-d : 指明导入文件存放在哪个数据库

-c : 指明导入文件存放在哪个集合

--type:指明要导入的文件格式。

--headerline:指明不导入第一行,csv格式的文件第一行为列名。

--file:指明要导入的文件路径。

./bin/mongoimport  -d  test  -c  dz  --type  csv  --file  /usr/local/src/dz.csv  --headerline

7.4、按照经纬度统计数据

我们规约的时候按照经纬度的5*5方格进行分组,如果在此方格内存在地震,则地震+1

var  map  =  function(){

var  jd  =  parseInt(this.jd/5)*5; var  wd  =  parseInt(this.wd/5)*5; var  area  =  jd  +  ':'  +  wd;

emit(area,1);//如果该区域有地震,则统计为1

}

var  reduce  =  function(area,nums){ return  Array.sum(nums);

}

db.dz.mapReduce(map,reduce,{out:'dzrs'});

成功获取区间范围内的地震次数,此时我们要将数据导出为json,做成热力图;

7.5 热力图

使 用 百 度 地 图 开 放 平 台 的 热 力 图 api http://lbsyun.baidu.com/index.php?title=jspopular

填入密钥,生成热力图

7.6 展示地震数据

转化地震数据为规定的json格式

var  course  =  db.dzrs.find();

var  row;

course.forEach(function(obj){

    row  =  obj._id.split(':');

    db.reli.insert({lng:parseInt(row[1])+2.5,lat:parseInt(row[0])+2.5,count:obj.value})

})

导出json

./bin/mongoexport  -d  test  -c  reli  -o  /usr/local/src/reli.json

将json数据放入热力图当中并配置热力图相关选项.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 安装 MongoDB Windowns、Ubuntu17.10 下安装 MongoDB教程在此 MongoDB 帮...
    Kangvcar阅读 2,089评论 0 13
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,898评论 2 89
  • 2018年7月5日笔记 1.MongoDB简介 1.1 NoSQL数据库是什么 NoSQL,指的是非关系型的数据库...
    潇洒坤阅读 615评论 0 0
  • 第一章 前言 1.1 知识体系分析 前端工程师:Web前端,也就是在Web应用中用户可以看得见碰得着的东西。包括W...
    whitsats阅读 865评论 0 3
  • docker 安装MongoDB 编辑docker-compose.yml文件 docker-compose up...
    巨子联盟阅读 337评论 0 0