Mongodb

  

1、Mongodb的介绍

  NoSQL,non-relational sql,非关系型数据库

2、Mongodb的安装和启动

  2.1 安装

    `sudo apt-get install -y mongodb-org`

  2.2 启动

    服务器端

      查看帮助:`mongdb --help`

      服务启动:`sudo service mongod start`

      服务停止:`sudo service mongod stop`

      服务重启:`sudo service mongod restart`

      查看是否启动成功:`ps aux|grep mongod`

      配置文件的位置:`/etc/mongodb.conf`

      默认端口:`27017`

      日志的位置:`/var/log/mongodb/mongod.log`

    客户端

      启动本地客户端:`mongo`

      查看帮助:`mongo --help`

      退出:`exit或者ctrl+c`

3、Mongodb的基本操作

  3.1 关于database的基础命令

    查看当前的数据库:`db`

    查看所有的数据库:`show dbs / show databases`

    切换数据库:`use db_name`

    删除当前的数据库:`db.dropDatabase()`

  3.2 关于集合的基础命令

    不手动创建集合:

      向不存在的集合中第一次加入数据时,集合会被创建出来

    手动创建集合:

      `db.createCollection(name,options)`

      `db.createCollection("stu")`

      `db.createCollection("sub",{capped:true,size:10})`

      参数capped:默认值为false表示不设置上限,值为true表示设置上限

      参数size:当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节

      查看集合:`show collections`

      删除集合:`db.集合名称.drop()`

  3.3 数据类型

    `Object ID`:文档ID

    `String`:字符串,最常用,必须是有效的utf8

    `Boolean`:存储一个布尔值,true或false

    `Integer`:整数可以是32位或64位,这取决于服务器

    `Double`:存储浮点值

    `Arrays`:数据或列表,多个值存储到一个键

    `Object`:用于嵌入式的文档,即一个值为一个文档

    `Null`:存储Null值

    `Timestamp`:时间戳,表示从1970-1-1到现在的总秒数

    `Date`:存储当前日期或时间的UNIX时间格式

  3.4 注意点

    (1)创建日期语句如下:

      参数的格式为YYYY-MM-DD

      `new Date("2017-12-30")`

    (2)每个文档都有一个数据,为_id,保证每个文档的唯一性

         可以自己去设置_id插入文档,如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectID

    (3)objectID是一个12个字节的十六进制数:

      1)前4个字节为当前时间戳

      2)接下来3个字节为机器的id

      3)接下来的2个字节为MongoDB的服务进程id

      4)最后3个字节是简单的增量值

  3.5 插入数据

    (1)在集合中插入数据:`db.集合名字.insert({"key":"value"})`

    (2 )在集合中查找数据:`db.集合名字.find()`

      Mongodb

    `db.集合名称.inset(document)`

    `db.stu.isnert({name:"gj",gender:1})`

    `db.stu.insert({_id:"20200507",name:‘gj‘,gender:1})`

    插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectId

  3.6 保存

    `db.集合名称.save(document)`

    如果文档的_id已经存在则修改,如果文档的_id不存在则添加

  3.7 查询

    `db.集合名称.find(<query>).pretty()`

    `db.集合名车.findOne()`  查询满足条件的一个

    参数query:查询条件

    pretry():美化输出

    例子`db.stu.find({age:18}).pretty()`

  3.8 更新

    `db.集合名称.update(<query>,<update>,{multi:<boolean>})`

    参数query:查询条件

    参数update:更新操作符

    参数multi:可选,默认是false,表示只更新找到的第一条记录,值为true表示把满足条件的文档全部更新

    

    `db.stu.update({name:"hr‘},{name:"mnc"})`  更新一条,所有值都会被替换,只留下name属性和值

    `db.stu.update({name:"hr"},{$set:{name:"hys"}})`   更新一条,$set配合update使用,指定一个值来更新

    `db.stu.update({},{$set:{gender:0}},{multi:true})`  更新全部,multi必须配合$符号一起使用,否则会无效    

    注意:“multi update only works with $ operators”

   3.9 删除

    `db.集合名称.remove(<query>,{justOne:<boolean>})`

    参数query:可选,删除的文档的条件

    参数justOne:可选,如果设为true或1,则只删除一条,默认为false表示删除多条

4、Mongodb数据查询

  4.1 数据查询

    (1)方法find():查询

      `db.集合名称.find({条件文档})`

    (2)方法findOne():查询,只返回第一个

      `db.集合名称.findOne({条件文档})`

    (3)方法pretty():将结果格式化

      `db.集合名称.find({条件文档}).pretty()`

    `db.stu.find({age:18}).pretty()`

  4.2 比较运算符

    (1)等于:默认是等于判断,没有运算符

    (2)小于:$lt  (less than)

    (3)小于等于:$lte  (less than equal)

    (4)大于:$gt  (greater than)

    (5)大于等于:$gte  (greater than equal)

    (6)不等于:$ne

    `db.stu.find(age:{$gte:18})`  查找年龄大于等于18的匹配项

  4.3 范围运算符

    使用“$in”,"$nin"判断是否在某个范围内

    例如:查询年龄为18、28或38的学生  `db.stu.find({age:{$in:[18,28,38]}})`

  4.4 逻辑运算符

    (1)and:在json中写多个条件即可

      例如:查询年龄大于或等于18,并且性别为true的学生  `db.stu.find({age:{$gte:18},gender:true})`

    (2)or:使用$or,值为数组,数组中每个元素为json

      例如:查询年龄大于18,或性别为false的学生  `db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})`

      例如:查询年龄大于18或性别为男生,并且姓名是小王  `db.stu.find({$or:[{age:{$gt:18}},{gender:false}],name:"xw"})`

  4.5 支持正则表达式

    使用//或$regex编写正则表达式

    例如:查询姓黄的学生  `db.stu.find({name:/^黄/})`  

       查询以花结尾的学生姓名  `db.stu.find({name:{$regex:"花$"}})` 

  4.6 limit和skip

    (1)方法limit():用于读取指定数量的文档

      `db.集合名称.find().limit(NUMBER)`

      例如:查询2条学生信息  `db.stu.find().limit(2)`

    (2)方法skip():用于跳过指定数量的文档

      `db.集合名称.find().skip(NUMBER)`

      例如:跳过前两条数据查询  `db.stu.find().skip(2)`

    (3)同时使用  `db.stu.find().limit(4).skip(5)`或`db.stu.find().skip(5).limit(4)`

  4.6 自定义查询

    使用$where后面写一个函数,返回满足条件的数据

    函数语法支持js

    例如:查询年龄大于30的学生

    ```

      db.stu.find({

        $where:function(){

          return this.age>30;

        }

      })

    ```

  4.7 投影

    在查询到的返回结果中,只选择必要的字段

    db.集合名称.find({条件},{字段名称:1,..})

    参数为字段与值,值为1表示显示,值为0不显示

    特殊:对于_id列默认是显示的,如果不显示需要明确设置为0

    例如:`db.stu.find({},{_id:0,name:1,gender:1})`

  4.8 排序

    方法sort(),用于对集合进行排序

    db.集合名称.find().sort({字段:1,...})

    参数1为升序排列

    参数-1为降序排列

    例如:根据性别降序,再根据年龄升序  `db.stu.find().sort({gender:-1,age:1})`

  4.9 统计个数

    方法count()用于统计结果集中文档条数

    `db.集合名称.find({条件}).count()`

    `db.集合名称.count({条件})`

    例如:`db.stu.find({gender:true}).count()`

           `db.stu.count({age:{$gt:200},gender:true})`

  4.10 消除重复

    方法distinct()对数据进行去重

    `db.集合名称.distinct("去重字段",{条件})`

    例如:`db.stu.distinct("hometown",{age:{$gt:18}})`

6、索引和备份

  6.1 备份的语法

    `mongodump -h dbhost -d dbname -o dbdirectory`

    -h:服务器地址,也可以指定端口号

    -d:需要备份的数据库名称

    -o:备份的数据存放位置,此目录中存放着备份出来的数据

    例如:`mongodump -h 192.168.0.103:27017 -d test -o ~/Desktop/testback`

  6.2 数据的恢复

    `mongorestore -h dhhost -d dbname --dir dbdirectory`

    -h:服务器地址

    -d:需要恢复的数据库实例

    --dir:备份数据所在位置

    `mongorestore -h 192.168.0.100:27017 -d test_back --dir ~/Desktop/testback/test`

7、MongoDB聚合

  7.1 聚合aggregate

    聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。

    db.集合名称.aggregate({管道:{表达式}}) 

    Mongodb

 

  7.2 常用管道命令

    在mongodb中,文档处理完毕后,通过管道进行下一次处理

    常用管道如下:

      `$group`:将集合中的文档分组,可用于统计结果

      `$match`:过滤数据,只输出符合条件的文档

      `$project`:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果

      `$sort`:将输入文档排序后输出

      `$limit`:限制聚合管道返回的文档数

      `$skip`:跳过指定数量的文档,并返回余下的文档

      `$unwind`:将数组类型的字段进行拆分

  7.3 表达式

    处理输入文档并输入

    语法:表达式:‘$列名‘   

    常用表达式:

    `$sum`:计算总合,$sum:1 表示以1倍计数

    `$avg`:计算平均值

    `$min`:获取最小值

    `$max`:获取最大值

    `$push`:在结果文档中插入值到一个数组中

    `$first`:根据资源文档的排序获取第一个文档数据

    `$last`:根据资源文档的排序获取最后一个文档数据

  7.4 $group

    (1)将集合中的文档分组,可用于统计结果

    (2)_id表示分组的依据,使用某个字段的格式为"$字段"

    例如:统计男生、女生的总人数

    ```

    db.stu.aggregate(

      {$group:{_id:"$gender",counter:{$sum:1}}}

    )

    ```

    (3)Group by null

      1)将集合中所有文档分为一组

      例如:求学生总人数、平均年龄

      ```

        db.stu.aggregate(

        {$group:{_id:null,counter:{$sum:1},avAge:{$avg:‘$age‘}}}  

      )

      ```

    (4)注意点

      1)$group对应的字典中有几个键,结果中就有几个键

      2)分组依据需要放到_id后面

      3)取不同的字段的值需要使用$,如`$gender`,`$age`

      4)取字典嵌套的字典中的值的时候用点`.`操作`$_id.country`

      5)能够同事按照多个键进行分组`{$group:{_id:{country:"$country",province:"$province"}}`

  7.5 $project

    修改输入文档的结构,如重命名、增加、删除字段、创建计算结果

    例如:查询学生的姓名、年龄

      ```

      db.stu.aggregate(

        {$project:{_id:0,name:1,age:1}}

      )

      ```

    例如:查询男生、女生人数,输出人数

      ```

      db.stu.aggregate(

        {$group:{_id:"$gender",counter:{$sum:1},avg_age:{$avg:"$age"}}},

        {$project:{_id:0,counter:1,avg_age:1,gender:"$_id",count:"$count",avg_age:"$avg_age"}}

      )

      ```

  7.6 $match

    用于过滤数据,只输出符合条件的文档,使用MongoDB的标准查询操作

    match是管道命令,能将结果交给后一个管道,但是find不可以

    例如:查询年龄大于20的学生

    ```

    db.stu.aggregate(

      {$match:{age:{$gt:20}}}

    )

    ```

    例如:查询年龄大于20的男生、女生人数

    ```

    db.stu.aggregate(

      {$match:{age:{$gt:20}}},

      {$group:{_id:"$gender",count:{$sum:1}}},

      {$project:{gender:"$_id",_id:0,count:"$count"}}

    )

    ``` 

  7.7 $sort

    将输入文档排序后输出

    例如:查询男生、女生人数,按人数降序

    ```

    db.stu.aggregate(

      {$group:{_id:"$gender",count:{$sum:1}}},

      {$sort:{count:-1}}

    )  

    ```

  7.8 $limit和$skip

    $limit

      限制聚合管道返回的文档数

      例如:查询2条学生信息

      ```

      db.stu.aggregate({$limit:2})

      ```

    $skip

      跳过指定数量的文档,并返回余下的文档

      例如:查询从第3条开始的学生信息

      ```

      db.stu.aggregate({$skip:2})      

      ```

    例如:统计男生、女生人数、按人数升序,取第二条数据

    说明:顺序是先写skip,再写limit

    ```

    db.stu.aggregate(

      {$group:{_id:"$gender",count:{$sum:1}}},

      {$sort:{count:1}},

      {$skip:1},

      {$limit:1}

    )

    ``` 

  7.9 $unwind

    将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值

    语法:`db.集合名称.aggregate({$unwind:"$字段名称"})`

    ```

    db.test.inset({_id:1,item:"t-shirt",size:["S","M","L"]})

    db.test.aggregate({$unwind:"$size"})

    ```

    属性preserveNullAndEmptyArrays值为false表示丢弃属性值为空的文档,为true表示保留属性值为空的文档

    用法:

    ```

    db.inventory.aggregate(

      {$unwind:{

        path:"$字段名称",

        preserveNullAndEmptyArrays:<boolean>  # 防止数据丢失

      }}

    )

    ```

8、创建索引

  8.1 创建索引

    索引:以提升查询速度

    建立索引的语法

      `db.集合.ensureIndex({属性:1})`  # 1表示升序,-1表示降序

      例如:`db.stu.ensureIndex({name:1})`

 

 

    测试:插入100000万条数据到数据库中(可以在mongo-cli中使用js语法)

      `for(i=0;i<1000000;i++){db.stu.insert({name:"test"+i,age:i})}`

    第一次查询时间:(executionTimeMillisEstimate的值)

      ```

      db.stu.find({name:"test100000"})

      db.stu.find({name:"test100000"}).explain("executionStats")

      ```

    建立索引后查询时间:

      ```

      db.stu.ensureIndex({name:1})

      db.stu.find({name:"test100000"}).explain("executionStats")      

      ```

  8.2 索引的使用

    (1)在默认情况下索引字段的值可以相同

    (2)创键唯一索引(索引的值是唯一的)

      `db.stu.ensureIndex({"name":1},{"unique":true})`

    (3)建立联合索引

      `db.stu.ensureIndex({name:1,age:1})`

    (4)查看当前集合的所有索引

      `db.stu.getindexes()`

    (5)删除索引

      `db.stu.dropIndex("索引名称")`

        

9、Mongo和python交互

  9.1 安装pymongo

    `pip install pymongo`

  9.2 使用代码

class TestMongo(object):
    def __init__(self):
        # 实例化一个client,连接到本地mongo服务器
        client = MongoClient(host="172.0.0.1",port=27017)
        # 使用方括号的方式选择数据库和集合
        self.collection = client["test"]["stu"]

    def test_insert(self):
        #insert接受字典,返回objectId
        ret = self.collection.insert_one({"name":"test_python_mongo"})
        print(ret)

    def test_insert_many(self):
        item_list = [{"_id":"{}",name:"test{}"}.format(i,i) for i in range(10)]
        # insert_many接受一个列表,列表中为所有需要插入的字典
        t = self.collection.insert_many(item_list)
        # t.inserted_ids为所有插入的id
        for i in t.inserted_ids:
            print(i)

if __name__=="__main__":
    obj = TestMonog()
    obj.test_insert()
    obj.item_insert_many()

 

    

 

Mongodb

上一篇:[ORALCE]SQL 优化案例之 同时取最大和最小


下一篇:Hibernate-Validator框架完成服务端参数据校验(巨详细)