Mongodb

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等同语句:
      <  > <e >e &ne
      
          {:}
          
          {:{$lt:}}
          
       >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)