zoukankan      html  css  js  c++  java
  • MongoDB 上手开发实践(入门上手就这一篇)

    前言

      MongoDB是一个介于 关系数据库 和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 json bson 格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立 索引

    也有一些其他的nosql的典型数据库,比如redis,hbase等,然而他们之间还是有区分的。(市面上有很多不错的数据库,这里就不一一列举了)

    name

    type

    mongodb

    面向文档

    redis

    键值存储

    hbase

    列存储

    官网必须知道的几个点
    1. 数据类型
    2. MongoDB CRUD Operrations 基础增删改查
    3. Aggregation 聚合操作
    4. 查询调优
    5. 索引

    123这三个点基本熟悉就代表能够满足平时的开发需求了,然后辅助一下数据结构设计的提升能更好的完成产品的开发;在123的基础上叠加45基本就能覆盖线上数据的搜索调优了。

    实践出真知,别问直接干它
     
      
     
      
    "实体结构"
    person:{
        name:"string",
        age:"int",
        children:"array person",
        parentId:"string"
    }

      创建表(collection)

    //命令行
    use test
    db.createCollection("person")  

      插入数据

    //插入一个爸爸
    db.person.insertOne({
        name:"Baba",
        age:Int32(1234),
        children:[],
        parentId:null
    })
    //插入了几个儿子
    db.person.insertOne({
        name:"Child1",
        age:Int32(234),
        children:[],
        parentId:null
    })
    
    db.person.insertMany(
    [{
        name:"Child2",
        age:Int32(235),
        children:[],
        parentId:null
    },{
        name:"Child3",
        age:Int32(236),
        children:[],
        parentId:null
    }
    ])

      

      创建数据OK了,但是作为一个有梦想的程序员,必须要再了解一下script,嘿嘿

    //循环大法
    for(var i=0;i<10;i++){
        db.person.insertOne({
        name:"robot"+i,
        age:Int32(Math.floor(Math.random() * 100)),
        children:[],
        parentId:null
    })
    }

      截止到上一步我们已经在数据库test中的person表插入了几条数据了,这里做几个简单的查询熟悉下数据查询

    //查询全部
    db.person.find({})
    //查询Baba
    db.person.find({name:"Baba"},{age:1}).sort({age:1})
    //查询不包含baba
    db.person.find({name:{$ne:"Baba"}})
    //查询年龄在(200,1000)的数据,$lte $gte中包含等于,时间的大于小于也是如此
    db.person.find({age:{$lt:1000,$gt:200}},{age:1,_id:0})
    //查询name中包含robot的数据,"i"代表忽略大小写,//就是正则
    db.person.find({name:/robot/i}).skip(0*5).limit(5)
    //或逻辑查询,$and为与逻辑,格式相同,而$and一般用于内嵌对象的与
    db.person.find({$or:[{name:"Baba"},{name:/chi/i}]})

      简单查询后,尝试一下update

    //将名字叫Child1的parentId修改为Baba的_id
    //将baba的children的arr中填充Child1的_id并且年龄+1
    //注意push和addtoset的区别
    var baba =  db.person.findOne({name:"Baba"});
    db.person.updateOne({name:"Child1"},{$set:{parentId:baba._id}})
    var child1 = db.person.findOne({name:"Child1"});
    db.person.updateOne({_id:baba._id},{$addToSet:{children:child1._id},$inc:{age:1}})
    //重复多次运行会发现CHILDREN会出现重复数据
    db.person.updateOne({_id:baba._id},{$push:{CHILDREN:child1._id}})
    //查询children中不包含指定id的数据
    db.person.find({children:{$in:[child1._id]}})
    
    
    //----------------------------华丽分割线---------------------------------------//
    
    
    //通过上面的语句会对set inc push addtoset有一定的了解,那就把CHILDREN中的移除吧,
    var baba =  db.person.findOne({name:"Baba"});
    var child1 = db.person.findOne({name:"Child1"});
    db.person.updateOne({_id:baba._id},{$push:{"CHILDREN":new ObjectId()}})
    db.person.updateOne({_id:baba._id},{$pull: {"CHILDREN":child1._id}})
    db.person.updateOne({_id:baba._id},{$set:{"CHILDREN":[]}})
    //查看存在CHILDREN字段的数据
    db.person.find({CHILDREN:{$exists: true}})
    //彻底删除字段
    db.person.updateMany({},{$unset:{"CHILDREN":""}})

      基本的CRUD我们已经知道了,接下来是MongoDB作为非关系型数据库厉害的地方了,聚合(aggregate)

    db.person.updateMany({name:/robot/i},{$set:{obj:[
        {key:"db",value:"mongo"}, 
        {key:"db",value:"redis"}, 
        {key:"db",value:"hbase"}
        ]}})
    
    db.person.aggregate()
          .match({name:/robot/i})  //query
          .project({nm:"$name",_id:1,age:1,obj:1})  //精简属性
          .unwind("$obj") //一般用来切分内嵌array,做数据聚合时经常会用到
          .group({ _id: "$nm", count: { $sum: 1 } }) //按照某个键分组聚合
          .sort({"count":-1})
          .limit(5)
    //这句比较特殊,处理内嵌数组对象的值,$elemMatch是筛选内嵌array对象的关键字,该查询匹配到的数据将会在Mongo内存中把内嵌array匹配到的对象置顶与array的第一个,而接下来的"obj.$.value"是将改内嵌array对象中的第一个的value修改成"mongodb"
    db.person.updateMany({obj:{$elemMatch: {value:"mongo"}}},{$set:{"obj.$.value":"mongodb"}})
    
    //类关系型数据库join
    db.person.aggregate(
    [{
        $lookup: {
               from: "person",
               localField: "_id",
               foreignField: "parentId",
               as: "sons"
         }
    }])

    mongodb version 4.0之后的版本新增了transaction(事务)的功能,真的可以向mysql,mssql那样回滚了,不是像redis事务那样的,大家可以去了解下。

      查询调优

      
    //这里match是让你填筛选条件,请别搞错
    db.collection.find({"match"}).explain("executionStats")
    
    //查询结果关键字含义
    executionStats.executionSuccess:是否执行成功
    executionStats.nReturned:满足查询条件的文档个数,即查询的返回条数
    executionStats.executionTimeMillis:整体执行时间
    executionStats.totalKeysExamined:索引整体扫描的文档个数,和早起版本的nscanned 是一样的
    executionStats.totalDocsExamined:document扫描个数, 和早期版本中的nscannedObjects 是一样的
    executionStats.executionStages:整个winningPlan执行树的详细信息,一个executionStages包含一个或者多个inputStages
    executionStats.executionStages.stage:这里是FETCH去扫描对于documents,后面会专门用来解释大部分查询使用到的各种stage的意思
    executionStats.executionStages.nReturned:由于是FETCH,所以这里该值与executionStats.nReturned一致
    executionStats.executionStages.docsExamined:与executionStats.totalDocsExamined一致executionStats.inputStage中的与上述理解方式相同
    explain.executionStats.executionStages.works:被查询执行阶段所操作的“工作单元(work units)”数。
    explain.executionStats.executionStages.advanced:优先返回给父stage的中间结果集中文档个数
    explain.executionStats.executionStages.isEOF:查询执行是否已经到了数据流的末尾
    
    //stage类型的含义
    COLLSCAN :全表扫描
    IXSCAN:索引扫描
    FETCH::根据索引去检索指定document
    SHARD_MERGE:各个分片返回数据进行merge
    SORT:表明在内存中进行了排序(与前期版本的scanAndOrder:true一致)
    SORT_MERGE:表明在内存中进行了排序后再合并
    LIMIT:使用limit限制返回数
    SKIP:使用skip进行跳过
    IDHACK:针对_id进行查询
    SHARDING_FILTER:通过mongos对分片数据进行查询
    COUNT:利用db.coll.count()之类进行count运算
    COUNTSCAN:count不使用用Index进行count时的stage返回
    COUNT_SCAN:count使用了Index进行count时的stage返回
    SUBPLA:未使用到索引的$or查询的stage返回
    TEXT:使用全文索引进行查询时候的stage返回

      索引

      索引方面直接点上方的链接吧,官方这个讲的还是比较好理解的,这里就不展开说了。相信各位小伙伴一看便知

     最后,响应一下咱们大大的口号 撸起袖子加油干,尝试一下心里就优普啦。谢谢大家

     

    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!

    本文版权归作者和博客园共有,来源网址:https://www.cnblogs.com/DanielYao/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利

  • 相关阅读:
    html的入门——从标签开始(2)
    Idea快捷键
    Java_core复习
    gitblit重置管理员密码【gitblit】
    使用命令创建git仓库
    Windows平台下搭建自己的Git服务器【gitblit】
    python笔记
    代码整洁之道
    Vue学习02
    Vue学习01
  • 原文地址:https://www.cnblogs.com/DanielYao/p/12174895.html
Copyright © 2011-2022 走看看