Mongodb

 

  1. 定义

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案,它是一个NoSQL。

NoSQL:非关系型数据库  NoSQL = Not Only SQL

  2. 关系型数据库和非关系型数据库的区别

关系型数据库:由行和列组成的二维表,有模式的,表是有关系的(连接查询,外键)。

非关系型数据库:无模式的,表之间无关系,且非关系型数据库存储的格式各不相同。

  3. HBase和Mongodb的区别

HBase:   面向列族存储的,KeyValue

Mongodb: 文档性数据库,BSON

 

SQL                   Mongodb

DataBase              DataBase         数据库

Table                 Collection       数据表/集合

row/record            Document         记录/文档

column/field          field            列/字段

primary key           primary key      主键

index                 index            索引

table joins           无

   4. 安装MongoDB

4.1、上传mongodb_rpms_3.6.2.tar.gz

4.2、解压

[hadoop@hadoop01 installPkg]$ tar -zxvf mongodb_rpms_3.6.2.tar.gz

4.3、因为需要将mongodb安装成系统服务,开机启动。此时需要root权限

   同时rpm默认安装在/usr/bin下,而/usr/bin的权限是root

   [hadoop@hadoop01 mongodb_3.6.2]$ sudo rpm -ivh *.rpm

4.4、配置文件在/etc/

[hadoop@hadoop10 bin]$ cd /etc/

[hadoop@hadoop10 etc]$ ll | grep mongo

-rw-r--r--.  1 root root    804 Jan 11  2018 mongod.conf

[hadoop@hadoop10 etc]$ sudo vim mongod.conf

# network interfaces

net:

  port: 27017

  bindIp: hadoop01 #空格不能省略

 

4.5、启动服务

[hadoop@hadoop10 etc]$ sudo service mongod start

[hadoop@hadoop10 etc]$ sudo chkconfig mongod on

 

4.6、使用客户端(mongo shell)连接

[hadoop@hadoop01 etc]$ mongo --help

[hadoop@hadoop10 etc]$ mongo --host hadoop01

 

 

  5. MongoDB是一个文档数据库

MongoDB中的记录是一个文档Document,它是由字段和值对组成的数据结构。MongoDB文档类似于JSON对象。字段的值可能包括其他文档、数组和文档数组。

 

Databases and Collections:

MongoDB在集合中存储BSON文档,即数据记录;在数据库中的集合中。

 

  6.Document结构:

{

   field1: value1,

   field2: value2,

   field3: value3,

   ...

   fieldN: valueN

}

 

字段名是字符串。文档的字段有以下的限制:

1、字段name为 _id保留作主键;它的值在集合中必须是唯一的,不可变的,并且可以是数组以外的任何类型。

2、字段名不能包含空字符。

3、顶级字段名不能以美元符号($)开头。

 

MongoDB使用点符号来访问数组的元素和嵌入文档的字段。

"<array>.<index>"

"<embedded document>.<field>"

 

  7. _id字段:

 

7.1、在MongoDB中,存储在集合中的每个文档都需要一个惟一的_id字段作为主键。如果插入的文档省略了_id字段,MongoDB驱动程序会自动为_id字段生成一个ObjectId。

 

7.2、_id字段具有以下行为和约束

默认情况下,MongoDB在创建集合时在_id字段上创建一个唯一的索引。

_id字段可以包含任何BSON数据类型的值,除了数组。

为了确保复制功能正常,不要在_id字段中存储BSON正则表达式类型的值。

 

  8. BSON数据类型:

Type         Number       Alias(笔名)   Notes(备注)

Double       1           “double”  

String       2         “string”  

Object      3         “object”  

Array       4          “array”  

Binary data     5          “binData”  

ObjectId      7           “objectId”  

Boolean     8          “bool”  

Date       9           “date”  

Null     10           “null”  

Regular Expression 11       “regex”  

JavaScript   13         “javascript”  

JavaScript (with scope) 15     “javascriptWithScope”  

32-bit integer   16       “int”  

Timestamp   17       “timestamp”  

64-bit integer   18     “long”  

Decimal128   19     “decimal”     New in version 3.4.

Min key     -1     “minKey”  

Max key     127     “maxKey”  

 

  9. ObjectId类型:

objectid很小,可能是惟一的,生成速度快,并且有序。ObjectId值的长度为12字节,包括:

一个4字节的时间戳值,表示ObjectId的创建,以Unix时代以来的秒为单位

一个5字节的随机值

一个3字节递增计数器,初始化为一个随机值

611b6745202d38df36b125b7 

 

mongo shell中,您可以使用ObjectId. getTimestamp()方法访问ObjectId的创建时间。

> var o = ObjectId()

> o.getTimestamp()

ISODate("2021-08-17T03:14:43Z")

 

 

 

 

 

 

  10. 操作数据库:

10.1、查看当前的数据库

> db

test

 

10.2、查看所有的数据库

> show databases

admin   0.000GB

config  0.000GB

local   0.000GB

 

> show dbs

admin   0.000GB

config  0.000GB

local   0.000GB

 

注意:如果数据库中没有数据,那么数据库不显示

 

10.3、切换数据库

> use mall

switched to db mall

 

注意:mongodb中use切换数据库,如果该库不存在,也可以切换,当插入数据的时候

该库就会创建。所以mongodb中不需要手动创建数据库。

 

10.4、查看数据库的状态

> db.stats()

{

        "db" : "mall",

        "collections" : 0,

        "views" : 0,

        "objects" : 0,

        "avgObjSize" : 0,

        "dataSize" : 0,

        "storageSize" : 0,

        "numExtents" : 0,

        "indexes" : 0,

        "indexSize" : 0,

        "fileSize" : 0,

        "fsUsedSize" : 0,

        "fsTotalSize" : 0,

        "ok" : 1

}

 

10.5、终端退出连接

> exit

ctrl+c

 

10.6、删除数据库

> db.dropDatabase()

删除当前指向的数据库

如果数据库不存在,则不做任何操作

 

  11. 操作集合

-------------------操作集合----------------

11.1 创建集合:

    db.createCollection(name, options)

    db.createCollection(<name>, { capped: <boolean>,

                              size: <number> } )

    name: 集合的名称

    capped:可选的。若要创建capped集合,请指定true。如果指定为true,还必须在size字段中设置最大大小。

    size: 可选的。为有上限的集合指定以字节为单位的最大大小。一旦有上限的集合达到其最大大小,MongoDB就会删除旧文档,为新文档腾出空间。size字段对于有上限的集合是必需的,对于其他集合则被忽略。

 

> db.createCollection("student")

{ "ok" : 1 }

 

mongodb使用过程中,是不需要创建集合

在对集合插入数据的时候,如果该集合不存在会自动创建

 

11.2 查看当前数据库中的集合:

> show tables

student

teacher

 

> show collections

student

teacher

 

11.3 删除集合:

   db.集合.drop()

 

> db.teacher.drop()

true

 

11.4 插入数据:

db.collection.insertOne(

   <document>,

   {

      writeConcern: <document>

   }

)

 

collection需要换成具体的集合名称

document就是插入的数据

writeConcern写数据的安全级别,是可选的,有默认值

 

> db.student.insertOne({name:"zhangsan",age:20})

{

        "acknowledged" : true,

        "insertedId" : ObjectId("611b542f6e4bbb2c2327f11f")

}

 

11.5 插入数据手动指定_id

> db.student.insertOne({_id:10001,name:"李四",sex:"男"})

{ "acknowledged" : true, "insertedId" : 10001 }

 

> db.student.insertOne({_id:10001,name:"wangwu",sex:"男"})

WriteError({

        "index" : 0,

        "code" : 11000,

        "errmsg" : "E11000 duplicate key error collection: test.student index: _id_ dup key: { : 10001.0 }",

        "op" : {

                "_id" : 10001,

                "name" : "wangwu",

                "sex" : "男"

        }

})

duplicate key error: 重复键错误

 

11.6 复合主键:

   _id的类型是一个document,就是复合主键

 

> db.student.insertOne(

 {

 _id:{

id:100,name:'id',info:"主键"

 },

  name:"hanmeimei",

  age:22

}

 )

 

{

        "acknowledged" : true,

        "insertedId" : {

                "id" : 100,

                "name" : "id",

                "info" : "主键"

        }

}

 

 

> db.student.insertOne(

 {

 _id:{

name:'id',info:"主键",id:100

 },

  name:"lucy",

  age:23

}

 )

 

{

        "acknowledged" : true,

        "insertedId" : {

                "name" : "id",

                "info" : "主键",

                "id" : 100

        }

}

 

注意:复合主键只有当kv内容一样,顺序一样才是相同的主键

 

11.7 db.collection.insertMany语法:

db.collection.insertMany(

   [ <document 1> , <document 2>, ... ],

   {

      writeConcern: <document>,

      ordered: <boolean>

   }

)

 

ordered:可选的。一个布尔值,指定mongod实例应该执行有序插入还是无序插入。默认值为true。

 

> db.student.insertMany(

   [

       {_id:1001,name:'lilei',age:20,sex:'male'},

       {_id:1002,name:'lily',address:'chengdu',hobbies:['music','boyfriend','eat']}

   ]

)

 

{ "acknowledged" : true, "insertedIds" : [ 1001, 1002 ] }

 

> db.student.insertMany(

   [

       {_id:1001,name:'lilei',age:20,sex:'male'},

       {_id:1003,name:'hanmeimei',address:'chengdu'}

   ]

)

BulkWriteError({

        "writeErrors" : [

                {

                        "index" : 0,

                        "code" : 11000,

                        "errmsg" : "E11000 duplicate key error collection: test.student index: _id_ dup key: { : 1001.0 }",

                        "op" : {

                                "_id" : 1001,

                                "name" : "lilei",

                                "age" : 20,

                                "sex" : "male"

                        }

                }

        ],

        "writeConcernErrors" : [ ],

        "nInserted" : 0,

        "nUpserted" : 0,

        "nMatched" : 0,

        "nModified" : 0,

        "nRemoved" : 0,

        "upserted" : [ ]

})

 

"nInserted" : 0  说明数据没有插入成功

因为以上数据采用的是有序插入,有序插入就是后面的数据需要等待前面数据插入成功,如果前面的数据插入失败,后面的数据也无法插入

 

> db.student.insertMany(

   [

       {_id:1001,name:'lilei',age:20,sex:'male'},

       {_id:1003,name:'hanmeimei',address:'chengdu'}

   ],

   {ordered:false}

)

BulkWriteError({

        "writeErrors" : [

                {

                        "index" : 0,

                        "code" : 11000,

                        "errmsg" : "E11000 duplicate key error collection: test.student index: _id_ dup key: { : 1001.0 }",

                        "op" : {

                                "_id" : 1001,

                                "name" : "lilei",

                                "age" : 20,

                                "sex" : "male"

                        }

                }

        ],

        "writeConcernErrors" : [ ],

        "nInserted" : 1,

        "nUpserted" : 0,

        "nMatched" : 0,

        "nModified" : 0,

        "nRemoved" : 0,

        "upserted" : [ ]

})

 

"nInserted" : 1 表示成功插入一条

因为使用了无序插入,前面数据的插入不影响后面数据的插入

 

 

 

11.8 db.collection.save语法:

db.collection.save(

   <document>,

   {

     writeConcern: <document>

   }

)

 

> db.student.save(

  {name:'bill',age:22}

)

如果文档不包含_id字段,则save()方法调用insert()方法。在操作期间,mongo shell将创建一个ObjectId并将其分配给_id字段。

 

如果数据的_id已经存在就是替换现有的文档

> db.student.save(

  {"_id" : ObjectId("611b6ab90ad895f9d53f39d9"),name:'bill01',age:22}

)

 

  12.查询数据

----------------查询数据-------------

12.1 db.collection.find(query, projection)

 

query:document类型,可选的。使用查询操作符指定选择筛选器。若要返回集合中的所有文档,请省略此参数或传递一个空文档({})。

projection:document类型,可选的。指定与查询筛选器匹配的文档中要返回的字段。若要返回匹配文档中的所有字段,请省略此参数。

 

根据条件查询语法:

{

  <field1>: <value1>,

  <field2>: { <operator>: <value> },

  ...

}

 

注意: <field1>: <value1>  表示等于

 

12.2 查询操作符:

Query Selectors - 比较:

$eq     Matches values that are equal to a specified value.(相等)

$gt     Matches values that are greater than a specified value.(大于)

$gte Matches values that are greater than or equal to a specified value.(大于等于)

$in     Matches any of the values specified in an array.(包含)

$lt     Matches values that are less than a specified value.(小于)

$lte Matches values that are less than or equal to a specified value.(小于等于)

$ne     Matches all values that are not equal to a specified value.(不等于)

$nin    Matches none of the values specified in an array.(不包含)

 

12.2.1、查询age是22的student信息

> db.student.find({

age:22

})

{ "_id" : ObjectId("611b6ab90ad895f9d53f39d9"), "name" : "bill01", "age" : 22 }

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

 

12.2.2、查询age大于22的student信息

> db.student.find({

age:{$gt:22}

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39db"), "name" : "rose", "age" : 23, "sex" : "female" }

 

12.2.3、查询name是hanmeimei的student信息

> db.student.find({

name:'hanmeimei'

})

{ "_id" : 1003, "name" : "hanmeimei", "address" : "chengdu" }

 

模拟数据:

db.student.insert(

  [

    {_id:{id:1001,"address":"shanghai"},name:"lisi",age:22},

    {_id:{id:1002,address:"beijing"},name:"tom",age:21}

  ]

)

 

12.2.4、查询主键中address是shanghai的student信息

key不是一个字段的时候,需要使用引号

> db.student.find({

'_id.address':'shanghai'

})

{ "_id" : { "id" : 1001, "address" : "shanghai" }, "name" : "lisi", "age" : 22 }

 

12.2.5、查询name是lisi,rose,hanmeimei的student信息

> db.student.find({

name:{$in:['lisi','rose','hanmeimei']}

})

 

{ "_id" : 1003, "name" : "hanmeimei", "address" : "chengdu" }

{ "_id" : ObjectId("611b6cb00ad895f9d53f39db"), "name" : "rose", "age" : 23, "sex" : "female" }

{ "_id" : { "id" : 1001, "address" : "shanghai" }, "name" : "lisi", "age" : 22 }

 

模拟数据:

db.student.insert({

id:1003,age:20,address:'未知'

})

 

12.2.6、查询name不是lisi,rose,hanmeimei的student信息

> db.student.find({

name:{$nin:['lisi','rose','hanmeimei']}

})

注意:$nin会返回值不在数组中的信息和数据中没有该字段的信息

 

 

  13.Query Selectors - 逻辑:

 

Name Description

$and 条件同时成立

$not 非(反转查询表达式的效果,并返回与查询表达式不匹配的文档。)

$nor 一个成立的取反。

$or     或,条件只要有一个成立即可

 

逻辑操作,条件至少有两个,所以$or后面应该是数组

 

13.1、查询age是22岁的女娃

> db.student.find({

age:22,sex:'female'

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

 

13.2、查询age是22岁的女娃

$and 条件同时成立,条件至少有两个,所以$and后面应该是数组

> db.student.find({

$and:[

   {age:22},

   {sex:'female'}

]

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

 

结论:当$and后面条件的字段不相同的时候,$and可以省略

 

13.3、查询age大于20小于23岁的女娃

> db.student.find({

$and:[

       {age:{$gt:20}},

       {age:{$lt:23}},

       {sex:'female'}

]

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

 

注意:如果$and连接的是相同的字段,可以省略$and,简写成:

> db.student.find({

age:{$gt:20,$lt:23},sex:'female'

})

 

13.4、查询姓名是andy或者年龄等于23的学生信息

$or  条件至少有两个,所以$or后面应该是数组

> db.student.find({

$or:[

      {name:'andy'},

      {age:23}

]

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

{ "_id" : ObjectId("611b6cb00ad895f9d53f39db"), "name" : "rose", "age" : 23, "sex" : "female" }

 

注意:字段不同的时候$or不能省略

 

13.5、查询姓名是andy或者tom学生信息

> db.student.find({

$or:[

      {name:'andy'},

      {name:'tom'}

]

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

{ "_id" : { "id" : 1002, "address" : "beijing" }, "name" : "tom", "age" : 21 }

 

> db.student.find({

name:{$in:['andy','tom']}

})

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

{ "_id" : { "id" : 1002, "address" : "beijing" }, "name" : "tom", "age" : 21 }

注意:如果$or后面的字段一样,效果和$in是一样的

 

13.6、查询年龄不小于22岁的学生信息

> db.student.find({

age:{$gte:22}

})

{ "_id" : ObjectId("611b6ab90ad895f9d53f39d9"), "name" : "bill01", "age" : 22 }

{ "_id" : ObjectId("611b6cb00ad895f9d53f39da"), "name" : "andy", "age" : 22, "sex" : "female" }

{ "_id" : ObjectId("611b6cb00ad895f9d53f39db"), "name" : "rose", "age" : 23, "sex" : "female" }

{ "_id" : { "id" : 1001, "address" : "shanghai" }, "name" : "lisi", "age" : 22 }

 

> db.student.find({

age:{$not:{$lt:22}}

})

 

13.7、查询姓名不是andy和tom,年龄不是23的学生信息

$nor 表示的是都不满足条件

> db.student.find({

$nor:[

      {name:{$in:['andy','tom']}},

      {age:23}

]

})

 

注意:$nor和前面的$not,$nin,$ne 一样,都会匹配出没有该字段的数据

 

官方文档:https://docs.mongodb.com