zoukankan      html  css  js  c++  java
  • MongoDB 小记

    之前本人说过一款非关系型数据库的代表 Redis 的 《 Redis 小记 》文章,觉得意犹未尽,今天就来介绍一款数据库 MongoDB ,先来看一下 

    MongoDB是一款基于分布式文件存储的数据库,是一种文档型数据库,是介于关系型和非关系型数据库之间的产品,是最接近关系型数据库的数据库。MongoDB中的每一条记录就是一个文档,是一个数据结构,由字段和值对组成,字段的值可能其他文档,数组,以及文档数组。一般用作离线数据分析使用,放在内网居多,提供高性能的数据持久化。

    以上为网上对于 MongoDB 的解释,总结起来就是一句话:好!

    老规矩,话不多说,直接开撸。

    关于 MongoDB 的安装就不介绍了,大家根据电脑版本型号自行搜索安装。

    安装并配置好 MongoDB 后我们在终端输入 db 及 show dbs 出现以下内容说明安装成功。MongoDB 默认数据库为 test 数据库,我们也可以自己创建数据库,如下。

    MongoDB 在创建数据库上还是很方便的,如上图,use test1 表示如果有 test1 这个数据库就切换到该数据库,如果没有则创建并切换到该数据库,通过 db 命令查看当前使用的数据库并且可以删除该数据库。

    如上图,db.createCollection( name , options ) 可以创建集合,其中 name 为必填项,为集合的名称,options 为可选项,选项中 capped 默认值为 false 表示不设置上限,值为 true 表示设置上限;当 capped 值为 true 时需设置 size 值,size 值为集合的上限,当超过上限时再插入数据会将之前的数据覆盖,单位为字节。

     

    如上图,MongoDB 通过 db.集合名称.insert( ) 向集合中添加数据,可以通过 db.集合名称.update( ) 对集合进行数据更新,db.集合名称.find() 对数据进行查找,操作中其实还有很多选填项,这个稍后会说。

     

    db.集合名称.remove( ) 可以对集合进行删除,第一个 { } 表示要删除数据的匹配项,第二个 { } 表示删除多个还是一个,true 表示只删除匹配到的第一个,false 表示删除匹配到的所有数据,db.集合名称.remove( { } ) 表示删除所有数据。

    从上面对 MongoDB 增删改查的基本操作我们发现其语法很接近 JavaScript 这类语言,对于我们这种初学者还是很友好的。但是语法上要比之前说过的 Redis 复杂一些,所以接下来的操作就不在终端进行操作了,移驾 Robo 3T (萝卜) 软件。

     

    图标就是上面这个长得跟萝卜似的大眼仔,直接下载安装即可。打开软件我们先进行如下配置。

     

    因为我们是在本地测试,所以 ip 为 127.0.0.1,端口号用 MongoDB 默认的 27017 端口。点击 Save 保存之后点击 Connect 进行连接即可。

    进来之后我们发现在错侧栏我们之前在终端创建的 test2 数据库还在,我们可以选中右键对其进行操作。我们也可以选中下方的 Collections 对其进行集合的操作,这些大家安装之后操作一下就可以了,很方便。右侧最上面黑条内可以输入我们想要的操作,对应的在下方会看到操作的输出结果,话不多说,操作起来。

    我们在之前终端创建的集合内插入 5 条数据,在软件右上角除可以对数据的显示状态进行切换。

    我们将其展示为直观的 json 数据格式。我们可以看出,在使用 MySQL 等关系型数据库时,主键都是设置自增的,但是在分布式环境下,这种方法就不可行了,会产生冲突,为此,MongoDB 采用了一个称之为 ObjectId 的类型来做主键,是一个随机生成的 BSON 类型的字符串,具体含义大家自行百度,不是重点。

    数据库中大部分操作都是围绕查询来进行操作的,这里我们着重看一下 MongoDB 在数据查询方面的写法。

    基本查询

    方法find():查询

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

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

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

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

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

    比较运算符

    • 等于,默认是等于判断,没有运算符

    • 小于$lt

    • 小于或等于$lte

    • 大于$gt

    • 大于或等于$gte

    • 不等于$ne

    • 例1:查询名称等于'nan1'的人

    db.user.find({name:'nan1'})

    运行结果如下:

    例2:查询年龄大于或等于18的人

    db.user.find({age:{$gte:18}})

    逻辑运算符

    • 查询时可以有多个条件,多个条件之间需要通过逻辑运算符连接

    • 逻辑与:默认是逻辑与的关系

    • 例3:查询年龄大于或等于20,并且性别为true的人

    db.user.find({age:{$gte:18},gender:true})

    逻辑或:使用$or

    例4:查询年龄大于20,或性别为 false 的人

    db.user.find({$or:[{age:{$gt:18}},{gender:false}]})

    运行结果如下:

    and和or一起使用

    例5:查询年龄大于18或性别为 true 的人,并且人的姓名为nan2

    db.user.find({$or:[{age:{$gte:18}},{gender:true}],name:'nan2'})

    运行结果如下:

    范围运算符

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

    例6:查询年龄为18、28的人

    db.user.find({age:{$in:[18,28]}})

    支持正则表达式

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

    例7:查询姓nan的人

    db.user.find({name:/^nan/})
    db.user.find({name:{$regex:'^nan'}}})

    自定义查询

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

    例7:查询年龄大于20的人

    db.user.find({$where:function(){return this.age>20}})

    Limit

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

    语法:

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

    参数NUMBER表示要获取文档的条数

    如果没有指定参数则显示集合中的所有文档

    例1:查询2条信息

    db.user.find().limit(2)

    skip

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

    语法:

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

    参数NUMBER表示跳过的记录条数,默认值为0

    例2:查询从第3条开始的user信息

    db.user.find().skip(2)

    一起使用

    方法limit()和skip()可以一起使用,不分先后顺序

    创建数据集

    for(i=0;i<15;i++){db.user.insert({_id:i})}

    查询第2至3条数据

    db.user.find().limit(2).skip(1)
    或
    db.user.find().skip(1).limit(2) 

    运行结果如下:

    投影

    在查询到的返回结果中,只选择必要的字段,而不是选择一个文档的整个字段

    如:一个文档有5个字段,需要显示只有3个,投影其中3个字段即可

    语法:

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

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

    对于需要显示的字段,设置为1即可,不设置即为不显示

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

    例1

    db.user.find({},{name:1,gender:1})

    例2

    db.user.find({},{_id:0,name:1,gender:1})

    运行结果如下:

    排序

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

    语法

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

    参数1为升序排列

    参数-1为降序排列

    例1:根据性别降序,再根据年龄升序

    db.user.find().sort({gender:-1,age:1})

    统计个数

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

    语法

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

    也可以与为

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

    例1:统计男人数

    db.user.find({gender:true}).count()

    例2:统计年龄大于20的男人数

    db.user.count({age:{$gt:20},gender:true})

    运行结果如下

    消除重复

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

    语法

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

    例:查找年龄大于18的性别(去重)

    db.user.distinct('gender',{age:{$gt:18}})

    运行结果如下:

    以上就是 MongoDB 在数据查询方面的基本操作,基本够我们的操作使用了。

    接下来我们说一下 MongoDB 语法中的高级应用 aggregate(聚合)。聚合主要用于计算数据,类似于 sql 中的 sum( ),avg( )。

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

    管道

    管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入

    ps ajx | grep mongo

    在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理

    常用管道

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

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

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

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

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

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

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

    表达式

    处理输入文档并输出

    语法

    表达式:'$列名'
    • 常用表达式

      • $sum:计算总和,$sum:1同count表示计数

      • $avg:计算平均值

      • $min:获取最小值

      • $max:获取最大值

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

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

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

    我们先看看之前我们添加进去的数据,我们在 user 集合中添加了五条数据,有 name ,age,gender 字段,其中 gender 字段 true 表示男,false 表示女。

    $group

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

    _id表示分组的依据,使用某个字段的格式为'$字段'

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

    db.user.aggregate([
        {$group:
            {
                _id:'$gender',
                counter:{$sum:1}
            }
        }
    ])

    运行结果如下:

    Group by null

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

    例2:求总人数、平均年龄

    db.user.aggregate([
        {$group:
            {
                _id:null,
                counter:{$sum:1},
                avgAge:{$avg:'$age'}
            }
        }
    ])

    运行结果如下:

    透视数据

    例3:统计 user 性别及姓名

    db.user.aggregate([
        {$group:
            {
                _id:'$gender',
                name:{$push:'$name'}
            }
        }
    ])

    运行结果如下:

    使用$$ROOT可以将文档内容加入到结果集的数组中,代码如下

    db.user.aggregate([
        {$group:
            {
                _id:'$gender',
                name:{$push:'$$ROOT'}
            }
        }
    ])

    运行结果如下:

    $match

    用于过滤数据,只输出符合条件的文档

    使用MongoDB的标准查询操作

    例:查询年龄大于20的人

    db.user.aggregate([
        {$match:{age:{$gt:20}}}
    ])

    运行结果如下:

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

    db.user.aggregate([
        {$match:{age:{$gt:20}}},
        {$group:{_id:'$gender',counter:{$sum:1}}}
    ])

    运行结果如下:

    $project

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

    例:查询 user 的姓名、年龄

    db.user.aggregate([
        {$project:{_id:0,name:1,age:1}}
    ])

    运行结果如下:

     

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

    db.user.aggregate([
        {$group:{_id:'$gender',counter:{$sum:1}}},
        {$project:{_id:0,counter:1}}
    ])

    运行结果如下:

    $sort

    将输入文档排序后输出

    例:查询 user 信息,按年龄升序

    db.user.aggregate([{$sort:{age:1}}])

    运行结果如下:

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

    db.user.aggregate([
        {$group:{_id:'$gender',counter:{$sum:1}}},
        {$sort:{counter:-1}}
    ])

    运行结果如下:

     

    $limit

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

    例:查询2条 user 信息

    db.user.aggregate([{$limit:2}])

    运行结果如下:

    $skip

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

    例:查询从第3条开始的 user 信息

    db.user.aggregate([{$skip:2}])

    运行结果如下:

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

    注意顺序:先写skip,再写limit

    db.user.aggregate([
        {$group:{_id:'$gender',counter:{$sum:1}}},
        {$sort:{counter:1}},
        {$skip:1},
        {$limit:1}
    ])

    运行结果如下:

    以上就是关于 MongoDB 聚合的一些操作,MongoDB 还有配置用户管理和设置数据库主从关系等操作,由于此篇幅过长,实在是写的太累了,有机会再说一下吧。

    总的来说 MongoDB 在数据的操作方面语法还是很贴切我们的日常操作语法的,用起来也很方便。

    好记性不如烂笔头,特此记录,与君共勉!

  • 相关阅读:
    大数据量磁盘文件排序
    Unix文件系统基本结构
    TCP三次握手和四次挥手
    哈希表的尴尬
    Http Get/Post请求的区别
    关于数据仓库中缓慢变化维的总结
    客户端回调过程..
    有关闭包的理解
    OWA半中文半英文问题,OWA实现邮件群发问题
    win2k3卷影副本服务的使用
  • 原文地址:https://www.cnblogs.com/weijiutao/p/10614857.html
Copyright © 2011-2022 走看看