美文网首页
MongoDB入门

MongoDB入门

作者: 为技术疯狂 | 来源:发表于2018-07-11 17:45 被阅读13次

    一、基本概念解释

    二、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数据放入热力图当中并配置热力图相关选项.

    相关文章

      网友评论

          本文标题:MongoDB入门

          本文链接:https://www.haomeiwen.com/subject/ugtkpftx.html