Mongodb

作者: 上山走18398 | 来源:发表于2019-07-09 07:32 被阅读0次

    Mongodb简介

    分布式存储,可扩展高性能的数据存储解决方案。介于关系和非关系数据库之间。面向文档的数据库
    
    文档?/? 逗号分隔的键值对文档结构??
    
    ```
    {
       _id: ObjectId(7df78ad8902c)
       title: 'MongoDB Overview', 
       description: 'MongoDB is no sql database',
       by: 'yiibai.com',
       url: 'http://www.yiibai.com',
       tags: ['mongodb', 'database', 'NoSQL'],
       likes: 100, 
       comments: [  
          {
             user:'user1',
             message: 'My first comment',
             dateCreated: new Date(2011,1,20,2,15),
             like: 0 
          },
          {
             user:'user2',
             message: 'My second comments',
             dateCreated: new Date(2011,1,25,7,45),
             like: 5
          }
       ]
    }  
    
    //_id 12字节的十六进制数,保证每一份文件的唯一性,(可以提供_id同时插入文档,不提供自己产生。
    //前4个字节为当前时间戳,未来3个字节的机器ID,接下来的2个字节的进程id MongoDB的服务器及剩余3个字节是简单的增量值。)
    
    ```
    
    • Nosql
      nosql(not only sql)

      (RDMBDs)关系数据库管理系统
      遵循ACID规则

    • 与关系型数据库的对比

    RDBMS Mongodb
    Database Database
    Table Collection
    Tuple/Row Document
    column Field
    Table Join Embedded Documents
    Primary Key Primary Key (Default key _id provided by mongodb itself)
    数据库服务器 客户端
    Mysqld/Oracle mongod
    mysql/sqlplus mongo

    Mongodb数据模型

    • mongodb设计模式的思考

      1.根据用户要求设计架构? //怎么样的架构是优化的?
        
      2.如果要将对象放在一起可以合并对象为一个文件,否则分开他们(确保不连接)
      
      3.重复数据有限?磁盘空间便宜?(相比计算时间)
      
      4.不需要连接写入,而是读
      
      5.优化架构是最常见的用例
      
      6.在模式上做复杂的聚集  //聚合操作?
      
    • 网上例子

       假设一个客户端需要一个数据库设计,设计一个博客网站,来看看 RDBMS 和 MongoDB 架构设计之间的差异。网站有以下要求。
      
        - 每一个文章内容都有独特的标题,描述和网址。
      
        - 每一个文章内容可以有一个或多个标签。
      
        - 每一个文章内容都有其出版商总数和喜欢的名称。
      
        - 每一个文章内容有评论以及名字,消息,时间和喜欢的用户。
      
        - 对于每个文章,可以是零个或多个评论。
      
        1.RDBMS模式设计
        
        通过post_id w外键连接各张表
        文章内容(post):id、 title、description、url、likes、post_by
        
        comment(评论):comment_id 、post_id、by_user、message、data_time、likes
        
        标签(tag_list):id 、post_id、tag
      
        
        2.MongoDB 模式  //只需要一个集合??
        
        {
           _id: POST_ID
           title: TITLE_OF_POST, 
           description: POST_DESCRIPTION,
           by: POST_BY,
           url: URL_OF_POST,
           tags: [TAG1, TAG2, TAG3],    //RDBMs模式下的tag_list
           likes: TOTAL_LIKES, 
           comments: [   
              {
                 user:'COMMENT_BY',
                 message: TEXT,
                 dateCreated: DATE_TIME,
                 like: LIKES 
              },
              {
                 user:'COMMENT_BY',
                 message: TEXT,
                 dateCreated: DATE_TIME,
                 like: LIKES
              }         //RDBMs模式下的comment表
           ]
        }
      

    搭建Mongodb环境

     RedHat/CentOs
     
     1. vi /etc/yum.repos.d/mongodb-org-3.4.repo 文件,一遍 yum 命令直接安装
     写入:
        [mongodb-org-3.4]
        name=MongoDB Repository
        baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
        gpgcheck=1
        enabled=1
        gpgkey=http://www.mongodb.org/static/pgp/server-3.4.asc
    //mongodb-org-server 提供默认的/etc/mongod.conf
    
    2. sudo yum install -y mongodb-org  (刚开始安装时,有点慢)
    
    3. 配置SEliNUX??
    
    4. 默认存放路径 /var/lib/mongo - 数据文件
        /var/log/mongodb -- rizhi wenjian 
        /etc/mongod.conf 可以指定备用日志和数据文件目录
        
    5. 启动Mongodb:
        
        # sudo service mongod start
        
        # mongod --dbpath=/data/mongodata/rs1 --logpath=/data/mongodata/rs1/rs1.log
        //命令行启动 绝对路径
        
        # mongod --config /var/lib/mongodb/conf/rs2.conf
        //以配置文件的方式启动,可以查看配置文件是否有错
        
        系统服务的方式启动
        # vi /etc/init.d/mongod
        
    6 注意事项:
        
        1. 当bindip 本地没有问题时 ,局域网内无法连接,首先看IP是否能ping通,防火墙是否关闭
        
        iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 27017 -j ACCEPT
    
        systemctl stop firewalld.service #停止firewall
        
        systemctl disable firewalld.service #禁止firewall开机启动
        
        firewall-cmd --state #查看默认防火墙状态(关闭后显示notrunning,开启后显示running)
    

    Mongodb语法

    • 创建数据库

      use database_name //如果不存在创建,存在则返回现有数据库
      
      //示例代码
      >use mydb
      switched to db mydb
      
      >show dbs  //有哪些数据库
      local     0.78125GB
      test      0.23012GB
      
      >db  //显示当前数据库
      mydb
      
      >db.movie.insert({"name":"yiibai tutorials"})    //当数据库中无数据时,不显示,插入数据后使用show命令就可以显示了
      >show dbs
      local      0.78125GB
      mydb       0.23012GB
      test       0.23012GB
      
      **dropDatabase**  //删除数据库
      >use mydb
      switched to db mydb
      >db.dropDatabase()    
      >{ "dropped" : "mydb", "ok" : 1 }
      >
      
    • 创建集合

      **createCollection()**
      1.db.createCollection(name, options) //Options  类型 Document     (可选)指定有关内存大小和索引选项
      //当插入文档,MongoDB 第一检查大小字段封顶集合,然后它会检查最大的字段中。
      
      >use test
      switched to db test
      >db.createCollection("mycollection")
      { "ok" : 1 }
      >
      2.在MongoDB中,不需要创建集合。当插入一些文件 MongoDB 自动创建的集合
      >db.yiibai.insert({"name" : "yiibai"})
      >show collections
      mycol
      mycollection
      system.indexes
      yiibai
      >
      
      3.drop() 
      db.COLLECTION_NAME.drop()
      
      >use mydb
      switched to db mydb
      >show collections
      mycol
      mycollection
      system.indexes
      yiibai
      >
      
      >db.mycollection.drop()         //删除mycollection集合
      true
      >
      
      >show collections
      mycol
      system.indexes
      yiibai
      >
      
      insert()
      >db.COLLECTION_NAME.insert(document)
      
      >db.mycol.insert({
      _id: ObjectId(7df78ad8902c),
      title: 'MongoDB Overview', 
      description: 'MongoDB is no sql database',
      by: 'tutorials yiibai',
      url: 'http://www.yiibai.com',
      tags: ['mongodb', 'database', 'NoSQL'],
      likes: 100
      })
      //_id: ObjectId(4 bytes timestamp, 3 bytes machine id, 2 bytes process id, 3 bytes incrementer)  _id自动生成id的命名规则
      
      
      //插入单个查询的多个文档
      >db.post.insert([
          {
             title: 'MongoDB Overview', 
             description: 'MongoDB is no sql database',
             by: 'tutorials yiibai',
             url: 'http://www.yiibai.com',
             tags: ['mongodb', 'database', 'NoSQL'],
             likes: 100
          },
          {
             title: 'NoSQL Database', 
             description: 'NoSQL database doesn't have tables',
             by: 'tutorials yiibai',
             url: 'http://www.yiibai.com',
             tags: ['mongodb', 'database', 'NoSQL'],
             likes: 20, 
             comments: [  
                {
                   user:'user1',
                   message: 'My first comment',
                   dateCreated: new Date(2013,11,10,2,35),
                   like: 0 
                }
             ]
          }
          ]) //为什么第一个记录可以没有comment字段呢???
      
      要插入文件
      db.mycollectionname.save(document) 与insert()类似
      
      
      
    • mongodb查找

        find()    | findOne()---此方法只返回一个文件
        
        db.COLLECTION_NAME.find()  //nd() 方法将在非结构化的方式显示所有的文件。
        
        >db.mycol.find().pretty() //格式化的显示结果
        
        RDBMS Where子句和MongoDB等同语句:
        &lt  &gt &lte &gte &ne
        
            {<key>:<value>}
            
            {<key>:{$lt:<value>}}
            
         >db.mycol.find({key1:value1, key2:value2}).pretty() 
         //类似于and条件
        
        
        //执行or语句 &or
        >db.mycol.find(
        {
          $or: [
             {key1: value1}, {key2:value2}
          ]
        }
        ).pretty()
        
        //执行and 和 or
        >db.mycol.find("likes": {$gt:10}, $or: [{"by": "yiibai"}, {"title": "MongoDB Overview"}] }).pretty()
        
        键的筛选:
        db.user.find({},{"_id":0})//指定find的第二个参数1则返回,0过滤
        
        关联查询:
        db.user.find("age":{"$in":[20,25,26]})
        
        db.user.find("age":{"$nin":[20,25,26]})
        
        特定类型的查询
        1. null
        db.user.find("sex":{"$in":[null]})//null不仅能匹配自身,还能匹配键不存在的文档
        2. 正则表达式
        db.user.find({"name":/^user/})
        3. 数组查询
        db.food.find({fruit:{$all:["apple","banana"]}})
        //$all 多个元素匹配
        //$size 查询指定长度的数组
        //$slice 返回数组的一个子集合
        db.blog.find({},{"comments":{"$slice":1}})  //[]偏移量
        
        内嵌文档查询:
        db.person.find({name:{first:"jock","last":"shob"}})
        db.person.find({"name.first":"jock"})
         
        $where    与JavaScript的结合
        
        游标:
        mongodb使用游标(cursor)来返回find的执行结果,客户端使用游标对最终结果进行有效的控制,比如分页,排序
        
        limit,skip和sort(1为升序,-1为降序)
        
        
        高级查询:
        包装查询
      

      update()

      db.COLLECTION_NAME.update(SELECTIOIN_CRITERIA, UPDATED_DATA)

      { "_id" : ObjectId(5983548781331adf45ec5), "title":"MongoDB Overview"}
      { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
      { "_id" : ObjectId(5983548781331adf45ec7), "title":"Tutorials Yiibai Overview"}

      db.mycol.update({'title':'MongoDB Overview'},{$set:{'title':'New MongoDB Tutorial'}})
      db.mycol.find()
      { "_id" : ObjectId(5983548781331adf45ec5), "title":"New MongoDB Tutorial"}
      { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
      { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}

      //MongoDB默认将只更新单一的文件,来更新多个你需要设置参数置'multi' 为true

      db.mycol.update({'title':'MongoDB Overview'},{$set:{'title':'New MongoDB Tutorial'}},{multi:true})

      save() //替换现有的文档和通过新的文档 save() 方法

      db.mycol.save(
      {
      "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai New Topic", "by":"Yiibai"
      }
      )
      db.mycol.find()
      { "_id" : ObjectId(5983548781331adf45ec5), "title":"Yiibai New Topic", "by":"Yiibai"}
      { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
      { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}

      remove() //从集合中删除文档,不加餐素默认整个删除,justOne可选参数,只删除一个文件

      db.COLLECTION_NAME.remove(DELLETION_CRITTERIA)
      //deletion criteria 删除标准

      { "_id" : ObjectId(5983548781331adf45ec5), "title":"MongoDB Overview"}
      { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
      { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}

    >db.mycol.remove({'title':'MongoDB Overview'})
    >db.mycol.find()
    { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
    { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}
    >
    
    Limit()  //限制输出记录的个数
    
    >db.COLLECTION_NAME.find().limit(NUMBER)
    
    { "_id" : ObjectId(5983548781331adf45ec5), "title":"MongoDB Overview"}
    { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
    { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}
        
    >db.mycol.find({},{"title":1,_id:0}).limit(2)
    {"title":"MongoDB Overview"}
    {"title":"NoSQL Overview"}
    >
    
    
    skip()方法  //跳过文档
    >db.mycol.find({},{"title":1,_id:0}).limit(1).skip(1)
    {"title":"NoSQL Overview"}
    >  //跳过第一个文档,只显示第二个文档
    
    sort()    //排序
    
    >db.COLLECTION_NAME.find().sort({KEY:1}) // 1用于升序排列,而-1用于降序。key为要搜索文档的键值
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ```
    
    • 数据类型
    String : 这是最常用的数据类型来存储数据。在MongoDB中的字符串必须是有效的UTF-8。
    
    Integer : 这种类型是用来存储一个数值。整数可以是32位或64位,这取决于您的服务器。
    
    Boolean : 此类型用于存储一个布尔值 (true/ false) 。
    
    Double : 这种类型是用来存储浮点值。
    
    Min/ Max keys : 这种类型被用来对BSON元素的最低和最高值比较。
    
    Arrays : 使用此类型的数组或列表或多个值存储到一个键。
    
    Timestamp : 时间戳。这可以方便记录时的文件已被修改或添加。
    
    Object : 此数据类型用于嵌入式的文件。
    
    Null : 这种类型是用来存储一个Null值。
    
    Symbol : 此数据类型用于字符串相同,但它通常是保留给特定符号类型的语言使用。
    
    Date : 此数据类型用于存储当前日期或时间的UNIX时间格式。可以指定自己的日期和时间,日期和年,月,日到创建对象。
    
    Object ID : 此数据类型用于存储文档的ID。
    
    Binary data : 此数据类型用于存储二进制数据。
    
    Code : 此数据类型用于存储到文档中的JavaScript代码。
    
    Regular expression : 此数据类型用于存储正则表达式
    
    操作符 $type
    
    db.col.find({"key":{$type:2}})  //查找key(键)类型为2的数据,2代表string                           
    
    • Mongodb 投影

      投影:只选择必要数据而不是选择一个文件的整个数据 比如find()方法

      find()  //显示文档的所有字段,需要设置字段列表值1或0。 
      //1用来显示字段而0是用来隐藏字段。
      
        { "_id" : ObjectId(5983548781331adf45ec5), "title":"MongoDB Overview"}
        { "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
        { "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Overview"}
        
        >db.mycol.find({},{"title":1,_id:0})
        
        {"title":"MongoDB Overview"}  //_id 字段不显示
        {"title":"NoSQL Overview"}
        {"title":"Yiibai Overview"}
        >
      
    • Mongodb 索引

      如果没有索引,Mongodbdb必须扫描每一个文档的集合,会有大量的数据需要处理
      数据结构: 树

      索引是一种特殊的数据结构,存储在一个容易遍历读取的数据集合中。索引是对数据库表中一列或多列的值进行排序的一种结构

        ensureIndex() 
        >db.COLLECTION_NAME.ensureIndex({KEY:1})
        //1是按升序排列的字段名称。要创建降序索引,需要使用-1
      
        >db.mycol.ensureIndex({"title":1})   //给title创建索引,1是升序,-1是降序
        >
        
        >db.mycol.ensureIndex({"title":1,"description":-1})  //为title创建索引(索引数据结构,给title建立索引排序 便于查找)
        
        2.接收可选参数
      
        //可选参数
        >db.mycol.ensureIndex({open:1,close:1},{background:true}) 
        
        >db.mycol.getINdexes()  //获得当前索引
      
      1. 索引深入学习
        //未加索引的状况,每个文档都要遍历一遍
        db.user.find({username:"user101"}).explain()   //explain 查看mongodb在执行查询过程中都干了什么
        {
            "cursor":"",
            "nscanned":100000000000000,
            "n":1,
            "millis":721,
            .....
        }
        上述中“nscanned”代表查询文档总数,“n”代表查询结果数 “millis”代表查询时间毫秒数 
        
        //添加索引,查询时间明显快速,最多只有64个索引(峰值),特定的集合上不应该有两个以上的索引,占内存 ,1代表方向
        db.user.ensureIndex({"username":1})
        db.user.find({username:"user101"}).explain()   //explain 查看mongodb在执行查询过程中都干了什么
        {
            "cursor":"",
            "nscanned":1,
            "n":1,
            "millis":3,
            .....
        }
        
    复合索引
    
    //索引的值时按一定顺序排列的,因此,使用索引键进行排序非常快
    >db.users.ensureIndex({"age":1,"username":1})  //这就是一个复合索引,多字段
    
    目的:优化查询,提高查询效率 理解引擎是如何工作的
    坑: 如果结果集的大小超过32MB,就会出错,拒绝对如此多的数据进行排序,操作符查询 
    基于多个查询条件进行排序是,索引方向才是比较重要的
    
    索引对象和数组
    //可以对任意深层次的字段建立索引
    >db.user.ensureIndex({"loc.city":1})   //city字段
    //db.user.find({"loc":{"ip":123,"city":shenzhen}})  对city字段才有效 ,对loc.city无效
    
    • Mongodb 聚合

      aggregate()  //处理数据(如统计平均值,求和),并返回数据结果。在SQL COUNT(*)和group by 相当于MongoDB的聚集
      //$sum  $avg  $min  $max $push $addToSet  $first  $last
          by_user: 'yiibai yiibai',
         url: 'http://www.yiibai.com',
         tags: ['mongodb', 'database', 'NoSQL'],
         likes: 100
          },
          {
             _id: ObjectId(7df78ad8902d)
             title: 'NoSQL Overview', 
             description: 'No sql database is very fast',
             by_user: 'yiibai yiibai',
             url: 'http://www.yiibai.com',
             tags: ['mongodb', 'database', 'NoSQL'],
             likes: 10
          },
          {
             _id: ObjectId(7df78ad8902e)
             title: 'Neo4j Overview', 
             description: 'Neo4j is no sql database',
             by_user: 'Neo4j',
             url: 'http://www.neo4j.com',
             tags: ['neo4j', 'database', 'NoSQL'],
             likes: 750
          },
          
          >db.mycol.aggregate([{$group:{_id:"$by_user",num_tutorial:{$sum:1}}}])
          
          {
             "result" : [
                {
                   "_id" : "yiibai yiibai",
                   "num_tutorial" : 2
                },
                {
                   "_id" : "yiibai yiibai",
                   "num_tutorial" : 1
                }
             ],
             "ok" : 1
          }
          >
      
      管道的概念:当前命令的输出结果作为下一个命令的参数
      Mongodb的聚合管道将Mongodb文档在一个管道处理完毕后将结果传递给下一个管道处理,管道操作时刻重复的
      $project:修改输入文档的结构,重新安排文档包含的字段(重命名,增加,删除)
      //db.article.aggregate(
      
      { $project : {
      
      _id : 0 ,   //不包含_id字段
      
      title : 1 ,  //包含该字段
      
      author : 1
      
      }});
      $match:过滤
      $limit
      $skip
      $unwind //目标字段不存在,该文档被忽略过滤
      $group :将集合中的文档进行分组,可用于统计结果
      //$group的时候必须要指定一个_id域,同时也可以包含一些算术类型的表达式操作符,无序的,不对大量个数的文档进行分组
      $sort
      $geoNear
      
    • Mongodb 复制

    • Mongodb 分片

    • Mongodb 关系

        表示多个文档之间的在逻辑上的联系
      文档间通过嵌入和引用来建立关系
      关系:
        1:1(1对1)
        1:N
        N:1
        N:N
      
      //user文件示例文档
      {
         "_id":ObjectId("52ffc33cd85242f436000001"),
         "name": "Tom Hanks",
         "contact": "987654321",
         "dob": "01-01-1991"
      }
      
      //address文件的示例文档结构:
      {
         "_id":ObjectId("52ffc4a5d85242602e000000"),
         "building": "22 A, Indiana Apt",
         "pincode": 123456,
         "city": "Los Angeles",
         "state": "California"
      } 
      
      

      嵌入建模

      {
         "_id":ObjectId("52ffc33cd85242f436000001"),
         "contact": "987654321",
         "dob": "01-01-1991",
         "name": "Tom Benzamin",
         "address": [
            {
               "building": "22 A, Indiana Apt",
               "pincode": 123456,
               "city": "Los Angeles",
               "state": "California"
            },
            {
               "building": "170 A, Acropolis Apt",
               "pincode": 456789,
               "city": "Chicago",
               "state": "Illinois"
            }]
      } 
          
      //这种方法保持在一个单一的文件,它可以很容易地检索和维护所有相关数据。 整份文件,可检索这样一个查询
      
      >db.users.findOne({"name":"Tom Benzamin"},{"address":1})
      
      缺点:嵌入的文档过长并且不断增加,影响读写性能
      

      模型引用关系
      如上把用户数据文档和用户地址数据文档分开维护,通过引用文档id字段来建立关系

      {
         "_id":ObjectId("52ffc33cd85242f436000001"),
         "contact": "987654321",
         "dob": "01-01-1991",
         "name": "Tom Benzamin",
         "address_ids": [
            ObjectId("52ffc4a5d85242602e000000"),  //引用的id对应的数据
            ObjectId("52ffc4a5d85242602e000001")
         ]
      } 
      
      //需要两个查询
      >var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1})
      >var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})
      
      

      Mongodb引用有两种:

        1.手动引用
      2.DBRefs(数据库引用)
      DBRef的形式:
      {
      $ref: 集合名称
      ,$id: 引用的id
      $db: 数据库名称,可选参数
          
      }
       
       {
           "_id":ObjectId("53402597d852426020000002"),
           "address": {
           "$ref": "address_home",
           "$id": ObjectId("534009e4d852427820000002"),
           "$db": "yiibai"},
           "contact": "987654321",
           "dob": "01-01-1991",
           "name": "Tom Benzamin"
        }
      
        >var user = db.users.findOne({"name":"Tom Benzamin"})
        >var dbRef = user.address
        >db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
      
    • 导入和导出

    mongoexport --help
    
    mongoexport -h 101.37.83.106:27017 -u txbyw -p txbyw -d tivs_audio -c Album --type=json -o /home/l123/Documents/mongodata_export_Album --authenticationDatabase admin
    
    mongoimport -h localhost -d tivs_audio -c Album /home/l123/Documents/mongodata_export_Album --authenticationDatabase admin
    

    相关文章

      网友评论

          本文标题:Mongodb

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