| 创建用户权限
| 数据类型 - null、boolean、Number、Float、String、Date、表达式、二进制、undefined、Array、Object
| 库操作 - show dbs、show collections、use db、db、db.dropDatabase()
| 创建和删除集合 - db.createCollection、db.myColl.insert({})、db.myColl.drop()
| 删除行 -
| 插入值 - db.myColl.insert({name: ‘haha’})
| 更新值 - db.myColl.update({name: ‘haha}, {$set: {age: 20}}, false, true)
| $set、$unset、$inc、$push、$pushAll、$pop、$pull、$pullAll、$rename
| 删除值 - db.myColl.remove({name: ‘’})、remove({})
| 查询值 - db.myColl.find({})
| .sort()、count()、limite()、skip()
| 查询条件 $gt、$gte、$lt、$lte、!= 、=、and、or、in、notIn
| 数组查询 $all、$size、$sclie
| $where 子句
| 索引 db.myColl.ensureIndex({key:1})、getIndexes()、dropIndexes()、background:true修改索引
| 索引类型: _id索引、单键索引、多键索引、复合索引、过期索引、全文索引、唯一索引
| 复制集
| 分片
| 数据均衡
| 性能分析

什么是MongoDB

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。

在高负载的情况下,添加更多的节点,可以保证服务器性能。

MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

一、MongoDB优点

    1、无数据结构限制(没有表结构概念,每条记录可以有完全不同的结构)

    2、完全的索引支持(单键索引、数组索引、全文索引、地理位置索引)

    3、数据安全性和分片扩展数据规模

    1、简单的单机服务    2、搭建具有冗余容错功能的复制集    3、搭建大规模数据集群        4、完成集群的自动部署

    MongoDB逻辑结构是一种层次结构,文档(document)、集合(collection)、数据库(database)这三部分组成的。 

二、数据库分类

    1、SQL数据库,支持SQL语言的数据库,如 Oracle,Mysql

    2、NoSQL数据库,不支持SQL语言的数据库,Redis, MongoDB

三、mongo与sql概念

    SQL术语/概念    MongoDB术语/概念    解释/说明

    database         database                 数据库
    table               collection             数据库表/集合
    row                   document                 数据记录行/文档
    column             field                     数据字段/域
    index               index                     索引
    table              joins                      表连接/MongoDB不支持
    primary key     primary key        主键/MongoDB自动将_id字段设置为主键

mongo的基本数据类型

null、boolean、Number、Float、String、Date、表达式、二进制、undefined、Array、Object

启动Mongodb

$ 启动Mongod服务 

    $ cd /usr/local/Cellar/mongodb/4.0.0/bin 

    $ mongod &

    $ 或者sudo ./mongod -f /usr/local/etc/mongod.conf &        // & 为后台运行

$ 停止服务 - 进入 use admin  => $ db.shutdownServer()

查看服务进程 -  ps -rf | grep mongod   ps -rf | grep mongo    kill -9 xxxx

1、命令启动Mongo服务

    // 指定配置文件启动mongod 服务
    mongod --dbpath=/usr/local/var/mongodb       // --logpath=/Users/thatway/mongodata/logs/mongodb.log

2、配置文件方式启动 

    mongod --config /usr/local/etc/mongod.conf

常用命令

$ db.getMongo() - 查看当前mongo的ip和端口

------------------ 库操作 ------------------

db.copyDatabase('旧数据库名', '新数据库名') - 克隆数据库

use myDataBase - 创建并切换库,如果没有就创建这个库,创建库时在内存中,只有对库插入集合操作才会真正存在硬盘上

db - 查看当前选择的库

db.dropDataBase() - 删除数据库,先切到要删除的库下在执行删除命令

db.copyDatabase('ibg_ndoe_sms', 'ibg_node_sms')

show dbs - 查询所有数据库


------------------ 集合 ------------------

show collections 或者 show tables - 查询当前数据库下所有的文档

db.createCollection(表名,指定大小和索引选项) - 创建集合

db.myColl.drop() - 删除当前库下指定集合

db.myColl.insert({_id: ObjectId("5a4b5f29cca1d978501c9c52"), name: 'aa', age: 30}) - 插入指定主键不能相同

db.myColl.save({_id: ObjectId("5a4b5f29cca1d978501c9c52"), name: 'aa', age: 30}) - 插入允许主键相同的数据


db.myColl.find(query) - 取数据

db.myColl.findOne() - 取第一条记录

db.myColl.update({}) - 更新文档

db.myColl.update({name: 'siguang'}, {$unset: {name: 1}}) - 删除一个字段

db.myColl.remove(query, {justOne}) - 删除一条文档


db.myColl.ensureIndex() - 创建索引

db.myColl.getIndexes() - 查看当前集合索引

db.myColl.dropIndexes() - 删除索引 

db.myColl.ensureIndex({id: 1}, {background: true}) - 修改索引


db.createUser() - 创建用户角色

库操作

一、查询库、查询集合

    1、show dbs — 查询所有的数据库列表

    2、show collections — 显示当前库下所有集合


二、创建库和删库

    1、use testDatabase — 创建一个数据库,如果库存在则使用当前库,创建时只在内存中,只有对这个库有操作后这个数据库才能真正创建

    2、db - 查看当前所在的库库

    3、db.dropDatabase() - 删除这个数据库

        use tsetDatabase     // 先进入要操作的数据库
        db.dropDatabase()     // 删除库

文档的创建和删除

查看常用的方法  db.myColl.help()

一、建两种方法

    1、db.createCollection(名称, 指定有关内存大小和索引选项);    -    创建集合

        options:
            capped - Boolean    (可选)如果为true,则启用封顶集合。封顶集合是固定大小的集合,会自动覆盖最早的条目,当它达到其最大大小。如果指定true,则需要也指定尺寸参数。
            autoIndexID - Boolean    (可选)如果为true,自动创建索引_id字段的默认值是false。
            size - number    (可选)指定最大大小字节封顶集合。如果封顶如果是 true,那么你还需要指定这个字段。
            max - number

    2、db.myColl.insert({name:’hf’,age:20}) — 在mongodb中在插入数据时即创建文档,此时创建的是名为myColl的文档

        for(i=0; i<100; i++) db.myTabel.insert({'age', i})        循环插入


二、删除集合、文档

    db.myColl.remove({type: '马尔代夫'}) - 删除myColl集合中 type='马尔代夫' 这条文档

    db.myColl.drop(); — 删除myColl这个集合

insert 插入文档

1、insert() - 插入主键不能相同,自动生成_id    db.myColl.insert({name:’hahaha’, age:12});

2、save() - 允许插入重复数据,直接添加一个文档

    db.myColl.save({        // 直接向集合中插入文档
        data: {},
        message: "操作成功",
        status: 0
    })

二者的区别

    insert()在主键相同时会报错

    save()在主键存在的为更新,如果不存在为插入

    // { "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang" }

    $ db.user.insert({ "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang" })        // 报错

    $ db.user.save({ "_id" : ObjectId("5a4b5df1cca1d978501c9c50"), "username" : "siguang123" })    // 执行成功,并将username的值改了

remove() 删除文档

1、db.myColl.remove({name: 'hf'}) - 删除name字段值为空的行, 此处相当于关系数据库中的 delete myColl where name = ‘hf’

2、db.myColl.remove({_id: ObjectId("593526143793ca468ceb963c")}) - 通过id来删除文档

3、db.myColl.remove({}) - 删除集合中所有文档

find 文档查询

http://www.cnmyColls.com/egger/p/3135847.html

1、findOne() - 查询第一条记录,然后闭关游标

2、find() - 返回所有记录

    // 返回满足字段值的文档
    db.role.find({age:30}) 

    // 指定返回的列,第一个参数为where语句,第二个参数为不显示列,0为不显示,1为显示
    db.cars.find({}, { user: 0 });

3、sort() - db.myColl.find().sort({age:1})      // age=1为升序,-1为降序  sort()

4、count() - db.myColl.count();          // 返回表中记录的个数 count()        

5、limit() - db.myColl.find().limit(5)          // 返回前5条数据 limit()

        db.myColl.find().skip(10).limit(20);        返回11-30条数据, 用于分页

6、skip() - db.myColl.find().skip(50)          // 跳过前50条数据

7、pretty() - 将查询出的内容进行格式显示        

8、查询条件

    1)条件查询  > $gt、 >= $gte、 < $lt、 <= $lte、 != $ne

        db.cars.find({carMoney: {$lt:100}})        // 查询carMoney小于100的值

        db.cars.find({carMoney: {$lt:100, $gt:20}})        // 查询carMoney 大于20小于100的值

    2)$and、$or、$in、$notIn

        $and  db.cars.find({name: '卡宴', price: 200})        // name=卡宴 并且 price=200    

        $or     db.cars.find({ $or: [ {id: 9}, {carType: 735}] })        // 查询出id=9 或者 carType=735

            // 查询 isDeleted: false 并且id带有'huang'字符 或者 carType等于735
            db.cars.find({ isDeleted: false, $or: [ {id: /huang/i}, {carType: 735}] });    

        $in      db.myColl.find({price: {$in: [100, 300, 500]});        // 查询出price 值为100、300、500值的字段

        $not    不包括的数据

9、$type 类型操作符查询

    例如: 将name字段中的所有为数字的查询出来, db.tourism.find({'name': {$type: 1}})

    对应表:
        类型                        数字            备注

        Double                            1                数字
        String                            2     
        Object                            3     
        Array                                4     
        Binary data                    5     
        Undefined                        6               已废弃。
        Object id                        7     
        Boolean                            8     
        Date                                9     
        Null                                10
        Regular Expression    11
        JavaScript                    13     
        Symbol                            14     
        JavaScript (with scope)    15     
        32-bit integer            16     
        Timestamp                        17     
        64-bit integer            18     
        Min key                            255            Query with -1.
        Max key                            127     


10、数组查询

    1)$all - 用来查询数组中是否包含指定的值

        // 内容列值为数组
        db.myColl.find({content: {$all: [1, 8]})        返回content中包含1或8的数组

    2)$size - 查询数组的长度

        db.myColl.find({content: {$size: 3}});        返回content数组字段长度为3个

    3)$slice - 控制指定字段中返回数组的个数

        db.myColl.find({}, {content: {$slice: 3}} )    返回所有记录 content数组只取前三个

        db.myColl.find({}, {content: {$slice: -3}} )    从后取3个

        db.myColl.find({}, {content: {$slice: [1, 3]}} )    取1-3的范围


11、$where 子句

    相当于用一个js查询一部分,如果为true则返回数据,则否不返回

    字符串形式
    db.myColl.find({$where: "this.title.length > 23"}, {title: 1})    对title field中的字符长度大于23的返回

    函数形式
    db.myColl.find({$where: function(){ return this.title.length > 23 }})


12、Example

    db.myColl.find()  —  查询myColl中的所有数据, 带条件 .fin({x: 1}) x=1的记录

    db.myColl.find({}, {id: 1, price: 1}) — 查询其中两个字段的值

    db.myColl.find({id: 5}, {username: 1}) - 只返回id=5 的 username的字段,其余的不返回

        { "_id" : ObjectId("58e85c84784a18c26f9a1fa5"), "username" : "siguang5" }

    db.myColl.update({}, {$unset:{'name':''}}, false, true)        // 删除一个字段

    db.myColl.find({title: /美舰/}, {title: 1})    -    查找出title中带有"美舰"的字符,并只返回title字段

update 更新文档

update(更新条件, 更新的值,[如果不存在是否创建 - 默认false],[是否更新全部 - 默认false])

1、$set - 更新值

    update() 第四个参数为true更所有匹配的值,false只更新一个

    // 只更匹配的第一条 如果type='123'不存在, 则插入一条只有name='456'的数据
    db.myColl.update({type: '123'}, {name: '456'});        // 注意如果不使用$set那么type=123这行记录只剩name=456

    // 更新全部匹配
    db.myColl.update({name:’hf’}, {$set:{age:25}}, false, true)

    // {multi:true} 更新多条
    db.myColl.update({'title':'MongoDB 教程'}, {$set:{'title':'MongoDB'}}, {multi:true})

    // 为集合中所有文档添加一个字段
    db.user.update({}, {$set: {password: '******'}}, {multi: 1})


2、$unset - 删除字段列

    db.myColl.update({id: 1}, {$unset: {content: 1}});        // 删除id=1,content字段


3、$inc - 只能对一个数字字段的值的进行累加,key不存在或者非数字都报错

    db.myColl.find({id: 1});        // result: { username: 'siguang', password: 100 }

    // 如果password的值存在则 +1000
    db.myColl.update({id: 1}, {$inc: {password: 1000}})    
    db.myColl.find({id: 1});        // result: { username: 'siguang', password: 1100 }


4、$push、$pushAll - 对一个数组字段在插入值

    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3 ] }

    db.myColl.update({id: 3}, {$push: {content: 4}})
    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3, 4] }


5、$addToSet - 向一个数组中添加数据,如果数组中存在这个值则不添加,如果不存在则添到数组中

    db.myColl.find({id: 3});            Result: { "id" : 3, "username" : "siguang3",  "content" : [ 1, 2, 3 ] }

    db.myColl.update({id: 3}, {$addToSet: {content: 3}});        // 数组中存在不添加
    db.myColl.update({id: 3}, {$addToSet: {content: 4}});        // "content" : [ 1, 2, 3, 4 ]


6、$pop - 删除数组中第一个或最后一个值 

    db.myColl.update({id: 3}, {$pop: {content: -1}});        // content为1 删除数组第一个值,-1删除数组最后一个值


7、$pull、$pullAll - 删除数组中指定相同的值

    db.myColl.update({id: 4}, {$set: {content: [1,2,34,4,1,2,3,1,1,6,1,34]}});    将content field为数组

    db.myColl.update({id: 4}, {$pull: {contentn: 1}});
    db.myColl.find({id: 4});        Result  {content: [2,34,4,2,3,6,34]}}  将数组中的1全部删除


8、$rename - 对某个字段进行更名

    db.myColl.update({id: 4}, {$rename: {content: 'title'}});        // 将id=4的 content field 名更改为title


http://chenzhou123520.iteye.com/myColl/1637629

索引

索引就是用来加速查询

索引的优缺点:

    优点: 索引加快查询的速度

    缺点: 增加磁盘空间消耗,降低写入性能

一、命令

    1、查看索引 - getIndexes()    db.myColl.getIndexes()

    2、创建、修改索引 - ensureIndex()    

        创建: db.myColl.ensureIndex({userId: 1})        // 1升序  -1降序

        上修改: db.myColl.ensureIndex({id: 1}, {background: true});        // {background: true}

    3、删除索引 - dropIndexes()

        db.myColl.dropIndexes(name);        // getIndexes()中查出来所索name的值


二、ensureIndex()参数

    1、background - Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。

    2、unique - Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.

    3、name - string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。

    4、dropDups - Boolean 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.

    5、sparse - Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.

    6、expireAfterSeconds - nteger    指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。

    7、v - index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。

    8、weights - document索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。

    9、default_language - string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语

    10、language_override - string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

http://blog.51cto.com/chenql/2071267


三、索引类型

    创建索引的两种不同:

        非全文索引 ensureIndex({key: value}): key为字段名,值为1或-1代表索引的排序方向
        全文索引     ensureIndex({key: 'text'}): key为字段名,value为固定的'text'字符串

    1、_id索引 - 是绝大多数集合默认建立的索引, 插入一条数据自动创建一个索引

    2、单键索引 - 最普通的索引 与_id不同的是,单键索引不会自动创建

            {x: 1, y: 2, z: 3}        // 当前表

            db.myColl.ensureIndex({x: 1})        // 使用 x 作为索引
            for(var i=0, i<10; i++) db.myColl.insert({x: 2, y: i+'y'; z: i+'z'});
            for(var i=0, i<10; i++) db.myColl.insert({x: 1, y: i+'y'; z: i+'z'});        // 插入10条数据,x为1
            db.myColl.find({x:1});            // 用索引查出数据


    3、多键索引 - 多键索引与单键索引创建形势相同

            单键索引: 值是一个单一的值,如字符串、数字或日期

            多键索引: 值有多个记录,如数组

            db.myColl.insert({x: [1,2,3,4,5]});


    4、复合索引 - 查询条件不只有一个,需要建立复合索引            

        db.myColl.ensureIndex({x: 1, y: 1})        // 定义复合索引
        db.myColl.find({x:1, y: 1})        // 通过复合索引查询

        设置后的索引:
        [
            {
                "v" : 2,
                "key" : {
                    "_id" : 1
                },
                "name" : "_id_",
                "ns" : "tuniu.gt"
            },
            {
                "v" : 2,
                "key" : {
                    "x" : 1,        // 这里
                    "y" : 1
                },
                "name" : "id_1_money_1",
                "ns" : "tuniu.gt"
            }
        ]


    5、过期索引 - 在一段时间后会过期的索引, expireAfterSeconds

        索引过期后数据会被删除, 插入的数据会在30秒后删除, 如用户登录信息, 存储日志

        db.myColl.ensureIndex({time: 1}, {expireAfterSeconds: 30})        // expireAfterSeconds 定义30秒后 time值的索引删除

        db.myColl.insert({username: 'siguang', password: 'xxxx', time: new Date()});        // new Date() 当前时间, 30秒后会自动删除当前这条记录

        ** 注意 当数据量不大的时候最小间隔为60秒, 就算设置30秒也会按60秒来完成 ** 
        ** 创建time的值必须是时间类型ISODate **


    6、全文索引

        *** 注意:mongo中不支持中文的全文索引 ***

        全文索引每次只能使用一个$text查询

        db.myColl.ensureIndex({key: "text"})

        db.myColl.ensureIndex({"$**": "text"})        对所有字段作全文索引,而不是某一个字段


        查询全文索引:

            db.myTabel.find({$test: {$search: 'aa'}})   只有值为aa时不包含其它字符时返回

            db.myTabel.find({$test: {$search: 'aa bb cc'}})   如果是 aa 或 bb 或 cc 时返回  相当于 ||

            db.myTabel.find({$test: {$search: 'aa bb -cc'}})  包含 aa 或 bb ,但不包含 cc 时返回

            db.myTabel.find({$test: {$search: '\'aa\' \'bb\' \'cc\''}})  aa bb cc 都包含  相当于 &&


        相适度: $meta

            {score: {$meta: 'textscore'}}  写在查询条件后面可以返回相似度的结果,与sort一起使用可以达到实用的效果

            Example:

            db.app.find({$text: {$search: '新京报'}}, {score: {$meta: 'textScore'}})

            // db.app.find({$text: {$search: '新京报'}}, {score: {$meta: 'textScore'}}).sort({scope: {$meta: 'textScore'}})       // scope值来排序

            { "_id" : ObjectId("58e31b4c47e9f10d47bd55ec"), "title" : "共享单车相随总理出国门", "article" : "今年1月,摩拜单车创始人", "author" : "新京报(北京)", "dateTime" : ISODate("2017-04-04T04:04:28.585Z"), "score" : 0.75 }
            { "_id" : ObjectId("58e31b4c47e9f10d47bd55ed"), "title" : "李克强赞这家企业一分钟穿越了两个时代", "article" : "当时,来这里考察的。", "author" : "新京报123(北京)", "dateTime" : ISODate("2017-04-04T04:04:28.624Z"), "score" : 0.75 }

            这里结果返回 scope 的值是就相适度的情况


四、索引属性

    1、name 为索引指定name值

        例如定义一个复合索引,可以统一给他们一个名这样,在删除索引的时候也可以通过名字来删除

        db.myColl.ensureIndex({id: 1, type: 1, money: 1}, {name: 'idx'});        // 定义索引name, 如果不加mongo会自动生成一个name值 为key_1

        db.myColl.dropIndexes('idx');


    2、unique 唯一索引

        唯一索引:不能在一个字段插入相同的值,如id如果有1,在插入id=1不允许

        db.myColl.ensureIndex({id: 1}, {unique: true/false});        // 设置了id字段为唯一索引

        db.myColl.insert({id:1, title:'xxx'});        如果id=1存在则不会被插入


    3、sparse 稀疏性


五、地理位置索引

    将一些点的位置存储在mongo中,创建索引后可以按照位置来查找其点

    子分类: 2d索引,用于存储和查找平面上的点        2dsphere索引,用于存储和查找球面上的点

    查找方式: 查找某个点一定距离内的点(打车软件)    查找包含在某个区域内的点

    1、创建 2D索引 平面地理位置索引

        db.location.ensureIndex({w: '2d'})        // 创建索引

        db.location.insert({w: [1, 1]});        // 插入经、纬度, 经度值在-180 至 180 之间, 纬度值在 -90 至 90 之间
        db.location.insert({w: [132, 112]});
        db.location.insert({w: [22, 14]});
        db.location.insert({w: [165, 13]});

        db.location.find({w: {$near: [1,1]}})        // $near 查找近的
        db.location.find({w: {$near: [1,140], $maxDistance: 150}})    // 查找经度 1-150之间, 或者纬度140-150之间   $maxDistrance 最大距离

聚合

aggregate() 主要用于处理数据,返回计算后的数据结果

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

    1、sum - 计算个数    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$sum : "$currentCount"}}}])

    2、avg - 计算平均值    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$avg : "$currentCount"}}}])

    3、min - 获取集合中所有文档对应值得最小值。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$min : "$currentCount"}}}])

    4、max - 获取集合中所有文档对应值得最大值。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$max : "$currentCount"}}}])

    5、push - 在结果文档中插入值到一个数组中。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$push: "$currentCount"}}}])

    6、addToSet - 在结果文档中插入值到一个数组中,但不创建副本。    db.mycol.aggregate([{$group : { _id: "$dimensionType", total: {$addToSet : "$currentCount"}}}])

    7、first - 根据资源文档的排序获取第一个文档数据。    db.mycol.aggregate([{$group : { _id: "$dimensionType", firstDoc: {$first : "$currentCount"}}}])

    8、last - 根据资源文档的排序获取最后一个文档数据    db.mycol.aggregate([{$group : { _id: "$dimensionType", firstDoc: {$last : "$currentCount"}}}])

    Example:

        // 查出来的文档
        db.col.find().pretty();        
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d0"),
            "dimensionType" : "AGE",
            "loanId" : "113029",
            "currentCount" : 30000,
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d1"),
            "dimensionType" : "OMG",
            "loanId" : "1129602",
            "currentCount" : 30000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d2"),
            "dimensionType" : "AGE",
            "loanId" : "113031",
            "currentCount" : 40000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d3"),
            "dimensionType" : "AGE",
            "loanId" : "113016",
            "currentCount" : 40000
        },
        {
            "_id" : ObjectId("59ae6c665f1fe4de50cb54d4"),
            "dimensionType" : "HSR",
            "loanId" : "112910",
            "currentCount" : 30000
        }

        1)通过游标来计算 dimensionType计算出类别的个数

            db.col.aggregate([
                {
                    $group:{
                        _id: "$dimensionType",
                        count: {$sum: 1}
                    }
                }
            ])        

            // 结果 返回
            { 
                "_id" : "HSR", 
                "count" : 1.0
            }
            { 
                "_id" : "OMG", 
                "count" : 1.0
            }
            { 
                "_id" : "AGE", 
                "count" : 3.0
            }

        2) 通过dimensionType列 中不同类型来计算 currentCount列的总合

            db.col.aggregate([
                {
                    $group:{
                        _id: "$dimensionType",
                        total: {$sum: "$currentCount"}
                    }
                }
            ])

            // 返回结果
            { 
                "_id" : "HSR", 
                "total" : 30000.0
            }
            { 
                "_id" : "OMG", 
                "total" : 30000.0
            }
            { 
                "_id" : "AGE", 
                "total" : 110000.0
            }


二、管道符:

    $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。

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

        db.col.aggregate([
            {
                $match: {
                    currentCount: {$gt: 30000}
                }
            },
            {
                $group:{
                    _id: "$dimensionType",
                    min: {$sum: "$currentCount"}
                }
            }
        ])
        先将currentCount字段大于30000的匹配出来,在通过分组取出currentCount的总和

    $limit:用来限制MongoDB聚合管道返回的文档数。

    $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。

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

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

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

    $geoNear:输出接近某一地理位置的有序文档。


三、count()  返回个数

    db.cars.count();        // 返回记录的个数

    db.cars.count({price: 1000})    // 返回price=1000 记录的个数

    db.cars.count({price: {$lt: 1000})    // 返回price < 1000 记录的个数


四、distinct()  指定某一个字段返回不重复的数据,如 age: 'a'  age: 'b'  age: 'a'   

    db.myColl.distinct("price");        // ['a', 'b']    

五、mapReduce()

游标

用户管理

mongo默认是没有管理员账户,需要在admin数据库中使用db.addUser()来添加管理员账号,否则任何人都可以操作数据库,admin库中有system.user的collection这就是用户表,用来存放超级管理员

用户分为两种: 一种是admin用户,另一种是在指定数据库的用户,admin用户是最高权限 

1、createUser() 创建用户

    $ use admin    // 先要切换到admin库

    $ show users     // 显示当前库下设置的所有设置的用户权限

    $ db.createUser(
        {
            user: "root",        // 用户名
            pwd: "ssssss",        // 密码
            roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
    )

    user - 段介绍: user字段,为新用户的名字;
    pwd - 用户的密码;
    cusomData - 为任意内容,例如可以为用户全名介绍;
    roles - 指定用户的角色,可以用一个空数组给新用户设定空角色;可以指定内置角色和用户定义的角色。


    内建的角色

        数据库用户角色:read、readWrite;

        数据库管理角色:dbAdmin、dbOwner、userAdmin;

        集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;

        备份恢复角色:backup、restore;

        所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase

        超级用户角色:root // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)

        内部角色:__system


    Roles(内置角色): 

        Read:允许用户读取指定数据库

        readWrite:允许用户读写指定数据库

        dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile

        userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户

        clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。

        readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限

        readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限

        userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限

        dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。

        root:只在admin数据库中可用。超级账号,超级权限


2、设置完用户权限进行重启mongod服务

    $ db.shtdownServer();        // 关闭mongod服务,或者kill掉

    // 进入bin目录下启动mongod

    $ mongod --auth                // 注意加权限就需要使用这个来启动服务,而不是单独的mongod &


3、mongo登录

    $ mongo --port 27017 -u "root" -p "ssssss" --authenticationDatabase "admin"

    $ use admin

    $ db.auth("root", "ssssss");        // 1表示登录成功,0表示登录失败。


4、创建其它用户

    use myCar
    db.createUser(
        {
            user: "car",
            pwd: "welcomeCar",
            roles: [ 
                { role: "readWrite", db: "myCar" },
                { role: "dbAdmin", db: "myCar" },
                { role: "clusterMonitor", db:"admin"}
            ]
        }
    )


5、作为其它用户进行连接和验证身份

    mongo --port 27017
    use myCar
    db.auth("car", "welcomeCar")


6、修改角色

    db.grantRolesToUser(
        "sms",
        [
            { role: "clusterMonitor", db:"admin"} 
        ]
    )

分片

MongoDB导入、导出及数据库备份与恢复

1、mongoexport - 将 collection 导出成JSON或CSV格式

    mongoexport  -d 库名  -c collection名   -o 输出的文件名   --type 导出的格式json/csv  -f  输出的字段,如果type是CSV需要指定字段名

    Example: sudo mongoexport -d tun -c gt -o gentuanyou --type json


2、mongoimport - 将 collection 导入到

    mongoimport  -d 库名  -c colection名  --file 导入的文件名   --type 导入的格式  -f 导入的字段名  --headerline 如果导入是csv则可以使用第一行标题 


3、mongodump - 库备份

    mongodump  -h 服务器地址   -d 数据库名   -o 备份的位置

    Example: mongodump -h 127.0.0.1 -d tun -o /Users/apple/siguang.liu/mongoBackup


4、mongorestore - 数据库恢复

    mongorestore  -h 服务器地址  -d 需要恢复的数据库   --dir 备份数据的位置    [--drop 恢复先删除数据,然后恢复数据]

    mongorestore -h 127.0.0.1 -d tun --dir /Users/apple/siguang.liu/mongoBackup

监控

对MongoDB服务的运行情况和性能进行监控

1、mongostat、mongoStop      mongostat是mongdb自带的状态检测工具, 查看mongo运行状态的程序

    使用: 先到bin目录 cd /usr/local/Cellar/mongodb/3.4.3/bin                进行 mongostat目录 $ mongostat --help   来查看文档

            mongostat -h 127.0.0.1:123    -u用户名 -p密码        执行侦听

    日志: 

        http://www.cnmyColls.com/zhuque/archive/2013/03/29/2988577.html

        insert    插入数量
        query    查询数量
        update  更新数量
        delete     删除数量
        getmore 
        command 
        flushes    虚拟映射
        mapped     
        vsize   占磁盘的空间
        res     占内存大小
        idx miss 如果值过高,说明索引创建的有问题
        qrw     qr 读队列,qw 写队列 性能指标的一块,如果值比较高出现性能问题
        arw 
        net_in 
        net_out 
        conn    连接mongo的数量            
        time

2、profile 集合介绍

    db.getProfilingStatus();        // 获取

3、日志介绍

4、explain(): 

    db.users.find({id: 10000}).explain('executionStats')

    explain()三个参数:'queryPlanner', 'executionStats', 和'allPlansExecution'

    result:
    {
        "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "myCar.users",
            "indexFilterSet" : false,
            "parsedQuery" : {
                "name" : {
                    "$eq" : "user99989"
                }
            },
            "winningPlan" : {
                "stage" : "COLLSCAN",
                "filter" : {
                    "name" : {
                        "$eq" : "user99989"
                    }
                },
                "direction" : "forward"
            },
            "rejectedPlans" : [ ]
        },
        "executionStats" : {
            "executionSuccess" : true,        // 是否成功
            "nReturned" : 1,                // 返回的数量
            "executionTimeMillis" : 49,        // *** 重要的执行时间   
            "totalKeysExamined" : 0,
            "totalDocsExamined" : 100000,    // 总共检查了多少个文档
            "executionStages" : {
                "stage" : "COLLSCAN",
                "filter" : {
                    "name" : {
                        "$eq" : "user99989"
                    }
                },
                "nReturned" : 1,
                "executionTimeMillisEstimate" : 50,
                "works" : 100002,
                "advanced" : 1,
                "needTime" : 100000,
                "needYield" : 0,
                "saveState" : 783,
                "restoreState" : 783,
                "isEOF" : 1,
                "invalidates" : 0,
                "direction" : "forward",
                "docsExamined" : 100000
            }
        },
        "serverInfo" : {
            "host" : "appledeMacBook-Pro-2.local",
            "port" : 27017,
            "version" : "3.4.3",
            "gitVersion" : "f07437fb5a6cca07c10bafa78365456eb1d6d5e1"
        },
        "ok" : 1
    }

MongoDB安装、连接、启动服务

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"    // 安装brew

$ brew update                // 更新brew

$ brew install mongodb         // 安装的目录 /usr/local/Cellar/mongodb/   

    brew uninstall mongodb  // 卸载mongo

$ brew list                    // 查看brew安装的列表中是否存在brew

$ sudo mkdir -p /data/db       // 用来存放mongo创建的数据文件

    注意这里如果启动服务时报/data权限问题需要执行

    $ sudo chmod -R 777 /data

$ 连接本地和远端服务器的mongoDB

    本地mongo: $ mongo             // 无密码

                        // 用户名admin、密码123456,登录本地端口为27017的test数据库
                        $ mongo mongodb://admin:123456@localhost:27017/test                    

    远端mongo: $ mongo 192.168.1.200:27017/test -u user -p password        // test为数据库名

        mongodb://10.10.13.123:27017,10.10.13.341:27017/ibg_node_core

$ 启动和关闭服务

    启动服务: 

        $ cd /usr/local/Cellar/mongodb/4.0.0/bin        // 进入到目录
        $ mongod &            // & 关闭终端mongod服务不会被kill掉  如果启用权限使用 mongod --auth

    关闭服务:

        $ use admin         // 需要先进入到admin库
        $ db.shutdownServer()

$ mongo --version            // 查看版本

https://www.imooc.com/article/23046

.conf配置文件

$ brew info mongodb    // 查看安装conf文件位置: mongod --config /usr/local/etc/mongod.conf

mongodb.conf:

    systemLog:                                // log目录                    
        destination: file
    path: /usr/local/var/log/mongodb/mongo.log
        logAppend: true
    storage:                                    // db目录
        dbPath: /usr/local/var/mongodb        // 数据存储的目录
    net:
        bindIp: 128.0.0.1
    security:
        authorization:enabled   // 开启权限

http://blog.csdn.net/sun491922556/article/details/74973191            // 3.4版本配置

收集

1、使用mongoShell语句来通过_id查询更新时需要加ObjectId(""), 如果程序处理不需要加

    db.col.update({_id: ObjectId("59acc404bef510c028190630")},{$set: {'by': 'mongodb'}})

填坑

1、首次安装 创建存放数据的目录时 

    $ sudo mkdir -p /data/db  如果这两个文件夹的权限是root那启动mongod就会报错,需要修改一下这两个目录的权限

    $ sudo chown apple:admin /data        // apple为我当前用户的名称

    $ sudo chown apple:admin /data/db

2、启动时如果提示 Failed to unlink socket file /tmp/mongodb-27017.sock errno:1 Operation not permitted

    因为/tmp/mongodb-27017.sock这个文件没有操作权限, 是root用户启动没成功后创建了这个文件
    需要到tmp目录下删除这个文件在重启

    $ cd /tmp && sodu rm -rf mongodb-27017.sock

3、Navicat Premium导出和导入集合

    导出:集合 -> 右键(导出向导)—> 选择导出文件类型json  
            注意:导出的json文件会在josn中自动创建一个RECORDSkey来存放数据,用于导出时的指定映射

    导入:集合 -> 右键(导入向导)—> 按步骤
            注意 第3步的时候 (表示一个集合行的标签 , 选择 "RECORDS"(Parent(Root))) ),勾选下面将标签属性视为集合字段
                    第7步,选择复制:删除目录全部记录,并从源重新导入

| http://www.mongoing.com // 中文网站
| http://www.jianshu.com/p/dd0c39bf7be4 // mongo安装
| http://www.runoob.com/mongodb/mongodb-objectid.html // 文档
| http://www.yiibai.com/mongodb/mongodb_drop_database.html
| http://blog.csdn.net/jaylong35/article/details/7219410 // 服务的开启与关闭
| http://blog.csdn.net/dbabruce/article/details/50963956 // 用户权限
| http://www.cnblogs.com/qingtianyu2015/p/5968400.html // 库的导入、导出
| https://robomongo.org // mongoDB可视化工具
|
| http://blog.csdn.net/u013457382/article/category/6114612
| http://www.cnblogs.com/zhongweiv/p/node_mongodb.html