mongo_mongodb - CSDN
mongo 订阅
MONGO,为裟椤双树所创作的小说作品《三界宅急送外传·异人学园》中的人物。 展开全文
MONGO,为裟椤双树所创作的小说作品《三界宅急送外传·异人学园》中的人物。
信息
外文名
MONGO
登场作品
《三界宅急送外传·异人学园》 《三界宅急送》纪念版
中文名
芒果
MessageBox函数
外形类似玉米,结构很复杂的生命体,皮安诺在班级组织的飞渡岭野营时发现了包裹其沉眠的石头,并将其带回家。
收起全文
精华内容
参与话题
  • mongodb基本概念和使用

    千次阅读 2018-06-30 17:43:02
    一、前言:NOSQL nosql:即not only sql,区别于应用于RDBMS(关系型数据库)的SQL(结构化查询语言)。SQL主要用于结构化存储的数据的查询与分析操作。而nosql支持类似sql的功能,但是与之相比没有那么多约束,显得...

    一、前言:NOSQL

        nosql:即not only sql,区别于应用于RDBMS(关系型数据库)的SQL(结构化查询语言)。SQL主要用于结构化存储的数据的查询与分析操作。而nosql支持类似sql的功能,但是与之相比没有那么多约束,显得更灵活。

        nosql通常泛指非关系型数据库,通常分为以下四大类:

    键值(Key-Value)存储数据库
    这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value模型对于IT系统来说的优势在于简单、易部署。但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。举例如:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB.
    列存储数据库。
    这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。如:Cassandra, HBase, Riak.
    文档型数据库
    文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB, MongoDb. 国内也有文档型数据库SequoiaDB,已经开源。
    图形(Graph)数据库
    图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。如:Neo4J, InfoGrid, Infinite Graph.
    因此,我们总结NoSQL数据库在以下的这几种情况下比较适用:1、数据模型比较简单;2、需要灵活性更强的IT系统;3、对数据库性能要求较高;4、不需要高度的数据一致性;5、对于给定key,比较容易映射复杂值的环境。

    二、mongodb基本概念

       2.1 mongodb是属于文档型的非关系型数据库,是开源、高性能、高可用、可扩展的(MongoDB is an open-source document database that provides high performance, high availability, and automatic scaling.

        下图为sql术语与mongodb术语的对比:


        数据逻辑层次关系:文档=>集合=>数据库


        通过对比,我们了解到,在关系型数据库中每一行的数据对应mongodb里是一个文档。mongodb的文档是以BSON(binary json)格式存储的,其格式就是json格式。

        

        2.2 一个document里可以包含多种类型的field,可以是日期、数字等,也可以是数组,还可以内嵌别的文档:

        var mydoc = {
                   _id: ObjectId("5099803df3f4948bd2f98391"),
                   name: { first: "Alan", last: "Turing" },
                   birth: new Date('Jun 23, 1912'),
                   death: new Date('Jun 07, 1954'),
                   contribs: [ "Turing machine", "Turing test", "Turingery" ],
                   views : NumberLong(1250000)

                }

        上面的document中:

    • _id是一个objectid,是一个唯一值
    • name则是包含了一个有2个field的嵌套文档
    • contribs是个数组
    • birth和death为date类型

        

        2.3 BSON支持的类型

    TypeNumberAliasNotes
    Double1“double” 
    String2“string” 
    Object3“object” 
    Array4“array” 
    Binary data5“binData” 
    Undefined6“undefined”Deprecated.
    ObjectId7“objectId” 
    Boolean8“bool” 
    Date9“date” 
    Null10“null” 
    Regular Expression11“regex” 
    DBPointer12“dbPointer”Deprecated.
    JavaScript13“javascript” 
    Symbol14“symbol”Deprecated.
    JavaScript (with scope)15“javascriptWithScope” 
    32-bit integer16“int” 
    Timestamp17“timestamp” 
    64-bit integer18“long” 
    Decimal12819“decimal”New in version 3.4.
    Min key-1“minKey” 
    Max key127“maxKey”

    三、mongodb特性及使用场景

        3.1 schema-free

        没有固定的行列组织结构,这是no-sql与rdbms最大的区别之一,同时mongodb也不需要预先定义字段类型与数量,可灵活增加或变更字段,对于频繁变化的业务的数据模型非常适合。

        3.2 文档结构

        mongodb是不支持集合与集合之间的join的,那么他是怎么解决RDBMS的表与表之间的关联关系呢?

        没错,就是直接将有关联的表信息组织成嵌套的层级文档结构。类似于RDBMS的大宽表概念,mongo的嵌套文档存储的方式的优点也很明显,减少了上层文档的数据冗余,如果是embedded data(内嵌)形式的话,是一次获取对应关系的所有明细数据。

        3.2.1 embedded data - 内嵌

        内嵌文档结构是直接将有关系的文档数据内嵌与其有关系的文档内。为了便于表达和理解,我们不妨称内嵌进去的文档为子文档,接受这个嵌入子文档的文档为父文档。那么,父文档与子文档之间的关系可以为一对一或者是一对多的关系。子文档是父文档的一个数组类型字段下的一个元素,数据中的元素可以是单个key-value,也可以是一个包含若干个字段的一个文档。

        内嵌文档适合一对一,一对多的业务数据场景。我们可以一直往父文档push子文档元素。对于电商中的购物车场景,一个购物车可以装很多商品,同时购物车在时间上和空间上也是有上限的。这在mongo的这种内嵌文档形式也很好实现,可以设置一个时间字段的TTL索引,选择一定时间进行删除国企商品信息数据。在查询时,通过购物车信息可以一次把对应的商品信息带出来。

    在这种一对多的关联查询中,mongo提供了很高效的查询效率。但是也有个问题,当内层文档数量有几十、上百万的时候,由于mongo document固定的文档大小限制,单个文档就存不下了。比较经典的实际场景就是在社交网络中,名人与粉丝的关系信息。要解决这个问题,我们可以用另一个方式:引用文档结构。

        

        3.2.2 Reference-引用

        顾名思义,这是在文档内引用别的文档的组织形式。如下图所示,contact和access都引用了user的的文档信息。

        引用文档结构与嵌入文档结构最大的区别就是后者是将关联的文档保存在一个大的文档里,而前者则是分开存储。这可以解决上文提到的一对多,而“多”是达到几十万甚至上百万的数据量的情况。这种结构的劣势也很明显,需要二次查询,增加了数据库的性能消耗。

        

           内嵌与引用的文档结构该怎么选择呢?

        官方文档也有做描述,大概如下:

    内嵌数据可以让应用程序把相关的数据保存在同一条数据库记录里面。这样一来,应用程序就可以发送较少的请求给MongoDB数据库来完成常用的查询及更新请求。

    一般来说,下述情况建议使用内嵌数据:

    • 数据对象之间有 “contains” (包含) 关系。 参见 一对一关系建模:内嵌文档模型

    • 数据对象之间有一对多的关系。 这些情况下 “多个”或者子文档会经常和父文档一起被显示和查看。

    一般来说,在下述情况下可以使用规范化模型(引用模型):

    • 当内嵌数据会导致很多数据的重复,并且读性能的优势又不足于盖过数据重复的弊端时候。

    • 需要表达比较复杂的多对多关系的时候。

    • 大型多层次结构数据集。


        3.3 other

        mongodb是针对大数据量的存储和查询的解决方案:在数据存储上支持自动分片和节点的水平扩展,可以存储海量的数据;在数据查询上支持二级索引、地理空间索引、TTL索引等,满足多种实际业务场景查询需求;在可靠性方面也支持高可用模式,在分片集群中,每个分片都有对应的副本,主分片挂了并不会影响业务使用。

        

        3.4 适用业务场景

    • 网站数据:MongoDB 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
    • 缓存:由于性能很高,MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后,由 MongoDB 搭建的持久化缓存层可以避免下层的数据源过载
    • 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储
    • 高伸缩性的场景:MongoDB 非常适合由数十或数百台服务器组成的数据库。MongoDB的路线图中已经包含对 MapReduce 引擎的内置支持
    • 用于对象及 JSON 数据的存储:MongoDB的 BSON 数据格式非常适合文档化格式的存储及查询

    四、CRUD操作

        可参考官网用户手册CRUD章节:https://docs.mongodb.com/manual/crud/


    参考资料:MONGO官网、mongo百度百科、MONGODB中文社区博客:http://www.mongoing.com/mongodb-advanced-pattern-design

    展开全文
  • mongo 介绍

    千次阅读 2017-01-15 23:28:33
    mongo 的 概念 mongo 的 部署 mongo 的使用 mongo 的运维 mongo 的文档 http://docs.mongoing.com/manual-zh/sharding.htmlmongo 的复制集和分片mongodb replica sets(复制集) 作用:提供了数据的冗余,...

    mongo 的 概念
    这里写图片描述

    mongo 的 部署
    这里写图片描述

    mongo 的使用
    这里写图片描述
    mongo 的运维
    这里写图片描述
    mongo 的文档 http://docs.mongoing.com/manual-zh/sharding.html

    mongo 的复制集和分片

    mongodb replica sets(复制集)
    作用:提供了数据的冗余,增加了高可用
    概念的梳理
    这里写图片描述

    复制集的概念
    复制集是从传统的主从结构演变而来,是由一组拥有相同数据集的mongod实例所组成的集群。
    复制集的特点:主是唯一的,当不是固定的,只有主节点可写,从节点只能读数据,当复制集中的节点只有
    主节点时复制集会将主节点降级为从节点,则复制集将不再提供写服务,只可读
    这里写图片描述
    在复制集中有两类节点
    数据节点和投票节点,数据节点:存储数据,可以充当主或则从节点,
    投票节点:负责选举,不存储数据,不能充当主或则从节点。

    安装和简单的启动一个mongo实例

    具体的安装过程和简单可以到别人的博客里看下
    进入bin目录
    有这些 程序 之后 用 mongod 启动一个 mongod的server服务

    这里写图片描述

    ./mongod -h

    一些常用的配置
    –port arg 默认27017,无论出于管理还是安全考虑都建议更改
    –bind_ip arg 只监听这个绑定的ip
    –logpath arg 日志路径
    –logappend 日志追加
    –pidfilepath arg 有利于脚本管理
    –fork
    –auth 开启验证
    –slowms arg 开启慢查询日志
    –profile arg 0=off 1=slow 2=all
    –syncdelay arg 刷盘间隔
    –oplogSize arg
    –replSet arg 复制集名

    [root@MiWiFi-R1CM bin]# ./mongod -f ../conf/mongod.conf
    about to fork child process, waiting until server is ready for connections.
    forked process: 13905
    child process started successfully, parent exiting

    这里的conf文件的配置之后会写

    下面来部署一个复制集
    新建并连接一台虚拟机
    host1:192.168.31.219

    [root@MiWiFi-R1CM ~]# ifconfig
    enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.31.219  netmask 255.255.255.0  broadcast 192.168.31.255
            inet6 fe80::a00:27ff:fe5f:664b  prefixlen 64  scopeid 0x20<link>
            ether 08:00:27:5f:66:4b  txqueuelen 1000  (Ethernet)
            RX packets 67  bytes 10597 (10.3 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 50  bytes 11397 (11.1 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    填写配置文件 3个28001.conf ,28002.conf ,28003.conf 分别代表了3个实例监听在不同对应的端口 贴出28001中的配置

    port=28001
    bind_ip=192.168.31.219
    dbpath=/usr/local/mongodb/data/28001/
    logpath=/usr/local/mongodb/log/28001.log
    logappend=true
    pidfilepath=/usr/local/mongodb/data/28001/mongo.pid 
    fork=true
    oplogSize=1024
    replSet=gegege

    启动这三个实例

    [root@MiWiFi-R1CM bin]# numactl --interleave=all ./mongod -f ../conf/28001.conf 
    about to fork child process, waiting until server is ready for connections.
    forked process: 2098
    child process started successfully, parent exiting
    [root@MiWiFi-R1CM bin]# ./mongod -f ../conf/28002.conf 
    about to fork child process, waiting until server is ready for connections.
    forked process: 2121
    child process started successfully, parent exiting
    [root@MiWiFi-R1CM bin]# ./mongod -f ../conf/28003.conf 
    about to fork child process, waiting until server is ready for connections.
    forked process: 2144
    child process started successfully, parent exiting
    
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      883/sshd            
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1456/master         
    tcp        0      0 192.168.31.219:28001    0.0.0.0:*               LISTEN      2098/./mongod       
    tcp        0      0 192.168.31.219:28002    0.0.0.0:*               LISTEN      2121/./mongod       
    tcp        0      0 192.168.31.219:28003    0.0.0.0:*               LISTEN      2144/./mongod  

    创建3个客户端进行连接测试

    这里写图片描述

    先进入28001的client

    > use admin
    > rs.initiate()
    {
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "192.168.31.219:28001",
        "ok" : 1
    }
    gegege:PRIMARY> rs.add('192.168.31.219:28002')
    { "ok" : 1 }
    gegege:PRIMARY> rs.add('192.168.31.219:28003')
    { "ok" : 1 }
    gegege:PRIMARY> rs.status()
    {
        "set" : "gegege",
        "date" : ISODate("2017-01-15T06:48:07.306Z"),
        "myState" : 1,
        "term" : NumberLong(1),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
            {
                "_id" : 0,
                "name" : "192.168.31.219:28001",
                "health" : 1,
                "state" : 1,
                "stateStr" : "PRIMARY",
                "uptime" : 76075,
                "optime" : {
                    "ts" : Timestamp(1484462881, 1),
                    "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2017-01-15T06:48:01Z"),
                "infoMessage" : "could not find member to sync from",
                "electionTime" : Timestamp(1484462773, 2),
                "electionDate" : ISODate("2017-01-15T06:46:13Z"),
                "configVersion" : 3,
                "self" : true
            },
            {
                "_id" : 1,
                "name" : "192.168.31.219:28002",
                "health" : 1,
                "state" : 2,
                "stateStr" : "SECONDARY",
                "uptime" : 7,
                "optime" : {
                    "ts" : Timestamp(1484462881, 1),
                    "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2017-01-15T06:48:01Z"),
                "lastHeartbeat" : ISODate("2017-01-15T06:48:05.699Z"),
                "lastHeartbeatRecv" : ISODate("2017-01-15T06:48:06.695Z"),
                "pingMs" : NumberLong(0),
                "syncingTo" : "192.168.31.219:28001",
                "configVersion" : 3
            },
            {
                "_id" : 2,
                "name" : "192.168.31.219:28003",
                "health" : 1,
                "state" : 2,
                "stateStr" : "SECONDARY",
                "uptime" : 5,
                "optime" : {
                    "ts" : Timestamp(1484462881, 1),
                    "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2017-01-15T06:48:01Z"),
                "lastHeartbeat" : ISODate("2017-01-15T06:48:05.698Z"),
                "lastHeartbeatRecv" : ISODate("2017-01-15T06:48:03.718Z"),
                "pingMs" : NumberLong(0),
                "configVersion" : 3
            }
        ],
        "ok" : 1
    }
    
    gegege:PRIMARY> use ljm
    gegege:PRIMARY> db.ljm.insert({"name":"lalala"})
    WriteResult({ "nInserted" : 1 })

    在主节点中插入一条数据
    切换到一个从节点

    gegege:SECONDARY> rs.slaveOk(1)
    gegege:SECONDARY> use ljm
    switched to db ljm
    gegege:SECONDARY> db.ljm.find()
    { "_id" : ObjectId("587b1ca519254fceb471077e"), "name" : "lalala" }
    

    复制集成员的 config的key的
    __id, host, arbiterOnly, priority , hidden, votes, slaveDelay, buildIndexes

    newconf = rs.conf();
    newconf.members[0].priority=5
    rs.reconfig(newconf)

    复制集的同步机制
    这里写图片描述

    gegege:PRIMARY> use local
    switched to db local
    gegege:PRIMARY> db.oplog.find()
    gegege:PRIMARY> db.oplog.rs.find()
    { "ts" : Timestamp(1484462773, 1), "h" : NumberLong("3501916664279793709"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "initiating set" } }
    { "ts" : Timestamp(1484462774, 1), "t" : NumberLong(1), "h" : NumberLong("8730864384105453179"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "new primary" } }
    { "ts" : Timestamp(1484462879, 1), "t" : NumberLong(1), "h" : NumberLong("-3557419064867120732"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 2 } }
    { "ts" : Timestamp(1484462881, 1), "t" : NumberLong(1), "h" : NumberLong("5364589923283900903"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 3 } }
    { "ts" : Timestamp(1484463269, 1), "t" : NumberLong(1), "h" : NumberLong("326681565887499179"), "v" : 2, "op" : "c", "ns" : "ljm.$cmd", "o" : { "create" : "ljm" } }
    { "ts" : Timestamp(1484463269, 2), "t" : NumberLong(1), "h" : NumberLong("-7126353079720928060"), "v" : 2, "op" : "i", "ns" : "ljm.ljm", "o" : { "_id" : ObjectId("587b1ca519254fceb471077e"), "name" : "lalala" } }

    1:重启一个实例以单机模式,
    通常再关闭server之前,使用rs.stepDown() 强制primary成为secondary

    2:重新创建一个新大小,
    其中包含旧的oplgo的入口条目的oplog

    3:重启mongod作为replica set的成员
    操作步骤:
    1>: Restart a Secondary in Standalone Mode on a Different Port
    关闭mongod实例:
    repset:PRIMARY> use admin
    repset:PRIMARY> db.shutdownServer()
    重启mongod实例以单机模式,修改端口,并不要加–replSet参数
    #vim /etc/mongo.conf
    dbpath=/var/lib/mongodb
    logpath=/var/log/mongodb/mongo.log
    pidfilepath=/var/run/mongo.pid
    directoryperdb=true
    logappend=true
    #replSet=repset
    bind_ip=192.168.1.100,127.0.0.1
    port=37017
    oplogSize=2000
    fork=true# mongod -f /etc/mongo.conf
    备份oplog# mongodump –db local –collection ‘oplog.rs’ –port 37017
    2>: Recreate the Oplog with a New Size and a Seed Entry
    保存oplog的最新的时间点

    use local
    db.temp.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )
    db.temp.find()
    删除旧的oplog
    db.oplog.rs.drop()
    3> :Create a New Oplog
    创建一个新的Oplog,大小为2G
    db.runCommand( { create: “oplog.rs”, capped: true, size: (2 * 1024 * 1024 * 1024) } )
    插入前面保存的旧的oplog的时间点的记录
    db.oplog.rs.save( db.temp.findOne() )
    db.oplog.rs.find()
    4>:Restart the Member:
    关闭单机实例:
    use admin
    db.shutdownServer()
    修改回配置# vim /etc/mongo.conf
    dbpath=/var/lib/mongodb
    logpath=/var/log/mongodb/mongo.log
    pidfilepath=/var/run/mongo.pid
    directoryperdb=true
    logappend=true
    replSet=repset
    bind_ip=192.168.1.100,127.0.0.1
    port=37017
    oplogSize=2000
    fork=true
    启动mongod
    # mongod -f /etc/mongo.conf
    重复上述步骤到所有需要更改的节点。

    复制集容灾选举(选举是容灾的一个过程,但容灾不只是选举,维护一个健康的集群是容灾的根本目的)
    1、 心跳检测
    2、维护主节点列表
    3、选举准备
    4、投票
    (了解集群中各个节点的状态信息,当某些节点不可达或新加入了一个节点时。
    从节点检测:在满足大多数原则的前提下,根据priority大小,是否是arbiter,optime是否在10s内,把自己加入主节点备选列表中。
    主节点检测:在满足大多数原则的前提下,判断是否有两个以上的主节点存在,根据priority大小选择合适的主节点。
    选举准备: 在集群中没有主节点时,在满足大多数原则的前提下,判断自己是否拿到线程锁和optime是否是最新的则标记自己为主节点

    分片的目的
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    这里写图片描述

    这里写图片描述

    shard 节点
    存储数据的节点(单个mongod或则复制集)
    confg server
    存储的元数据(定位数据的信息) 为mongos 服务.将数据路由到shard
    mongos
    接受前段的请求 进行对应的消息路由

    在192.168.31.159部署4个shard分片和config节点
    启动4个shard节点

    [root@MiWiFi-R1CM bin]# 
    ./mongod --shardsvr --logpath=/opt/log/s1.log --logappend --dbpath=/opt/data/s1 --fork --port 27017
    ./mongod --shardsvr --logpath=/opt/log/s2.log --logappend --dbpath=/opt/data/s2 --fork --port 27018
    ./mongod --shardsvr --logpath=/opt/log/s3.log --logappend --dbpath=/opt/data/s3 --fork --port 27019
    ./mongod --shardsvr --logpath=/opt/log/s4.log --logappend --dbpath=/opt/data/s4 --fork --port 27020
    tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      3350/./mongod       
    tcp        0      0 0.0.0.0:27018           0.0.0.0:*               LISTEN      3368/./mongod       
    tcp        0      0 0.0.0.0:27019           0.0.0.0:*               LISTEN      3394/./mongod       
    tcp        0      0 0.0.0.0:27020           0.0.0.0:*               LISTEN      3412/./mongod 
    [root@MiWiFi-R1CM bin]# ./mongod --port 27100 --dbpath=/opt/config --logpath=/opt/log/config.log --logappend --fork
    about to fork child process, waiting until server is ready for connections.
    forked process: 3791
    child process started successfully, parent exiting

    在192.168.31.228启动一个mongos的节点

    [root@MiWiFi-R1CM bin]# 
    ./mongos --port 27017 --logappend --logpath=/opt/log/mongos.log --configdb 192.168.31.159:27100 --fork
    2017-01-15T20:38:49.859+0800 W SHARDING [main] Running a sharded cluster with fewer than 3 config servers should only be done for testing purposes and is not recommended for production.
    about to fork child process, waiting until server is ready for connections.
    forked process: 3391
    child process started successfully, parent exiting

    添加分片

    [root@MiWiFi-R1CM bin]# ./mongo 127.0.0.1:27017
    MongoDB shell version: 3.2.9
    connecting to: 127.0.0.1:27017/test
    mongos> use admin
    switched to db admin
    mongos> db.runCommand({"addShard":"192.168.31.159:27017"})
    { "shardAdded" : "shard0000", "ok" : 1 }
    mongos> db.runCommand({"addShard":"192.168.31.159:27018"})
    { "shardAdded" : "shard0001", "ok" : 1 }
    mongos> db.runCommand({"addShard":"192.168.31.159:27019"})
    { "shardAdded" : "shard0002", "ok" : 1 }
    mongos> db.runCommand({"addShard":"192.168.31.159:27020"})
    { "shardAdded" : "shard0003", "ok" : 1 }
    mongos> db.runCommand({ enablesharding:"ljm" })
    { "ok" : 1 }
    mongos> db.runCommand({ shardcollection: "ljm.user", key: { _id:hashed}})
    { "collectionsharded" : "ljm.user", "ok" : 1 }

    分片测试

    mongos> for(var i=0;i<10000;i++){db.user.insert({user_id:i%200,time:ISODate(),size:1,type:2})}
    WriteResult({ "nInserted" : 1 })
    db.runCommand({enablesharding:"ljm"})
    db.runCommand({shardcollection:"ljm.user",key:{_id:1}})
    db.user.stats()
    {
        "sharded" : true,
        "capped" : false,
        "ns" : "ljm.user",
        "count" : 10000,
        "size" : 810000,
        "storageSize" : 262144,
        "totalIndexSize" : 94208,
        "indexSizes" : {
            "_id_" : 94208
        },
        "avgObjSize" : 81,
        "nindexes" : 1,
        "nchunks" : 1,
        "shards" : {
            "shard0000" : {
                "ns" : "ljm.user",
                "count" : 10000,
                "size" : 810000,
                "avgObjSize" : 81,
                "storageSize" : 262144,
                "capped" : false,
                "wiredTiger" : {
                    "metadata" : {
                        "formatVersion" : 1
                    },
                    "creationString" : "allocation_size=4KB,app_metadata=(formatVersion=1),block_allocation=best,block_compressor=snappy,cache_resident=0,checksum=on,colgroups=,collator=,columns=,dictionary=0,encryption=(keyid=,name=),exclusive=0,extractor=,format=btree,huffman_key=,huffman_value=,immutable=0,internal_item_max=0,internal_key_max=0,internal_key_truncate=,internal_page_max=4KB,key_format=q,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=64MB,log=(enabled=),lsm=(auto_throttle=,bloom=,bloom_bit_count=16,bloom_config=,bloom_hash_count=8,bloom_oldest=0,chunk_count_limit=0,chunk_max=5GB,chunk_size=10MB,merge_max=15,merge_min=0),memory_page_max=10m,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=0,prefix_compression_min=4,source=,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,type=file,value_format=u",
                    "type" : "file",
                    "uri" : "statistics:table:collection-2--3716031408657191999",
                    "LSM" : {
                        "bloom filter false positives" : 0,
                        "bloom filter hits" : 0,
                        "bloom filter misses" : 0,
                        "bloom filter pages evicted from cache" : 0,
                        "bloom filter pages read into cache" : 0,
                        "bloom filters in the LSM tree" : 0,
                        "chunks in the LSM tree" : 0,
                        "highest merge generation in the LSM tree" : 0,
                        "queries that could have benefited from a Bloom filter that did not exist" : 0,
                        "sleep for LSM checkpoint throttle" : 0,
                        "sleep for LSM merge throttle" : 0,
                        "total size of bloom filters" : 0
                    },
                    "block-manager" : {
                        "allocations requiring file extension" : 33,
                        "blocks allocated" : 33,
                        "blocks freed" : 0,
                        "checkpoint size" : 253952,
                        "file allocation unit size" : 4096,
                        "file bytes available for reuse" : 0,
                        "file magic number" : 120897,
                        "file major version number" : 1,
                        "file size in bytes" : 262144,
                        "minor version number" : 0
                    },
                    "btree" : {
                        "btree checkpoint generation" : 3,
                        "column-store fixed-size leaf pages" : 0,
                        "column-store internal pages" : 0,
                        "column-store variable-size RLE encoded values" : 0,
                        "column-store variable-size deleted values" : 0,
                        "column-store variable-size leaf pages" : 0,
                        "fixed-record size" : 0,
                        "maximum internal page key size" : 368,
                        "maximum internal page size" : 4096,
                        "maximum leaf page key size" : 2867,
                        "maximum leaf page size" : 32768,
                        "maximum leaf page value size" : 67108864,
                        "maximum tree depth" : 3,
                        "number of key/value pairs" : 0,
                        "overflow pages" : 0,
                        "pages rewritten by compaction" : 0,
                        "row-store internal pages" : 0,
                        "row-store leaf pages" : 0
                    },
                    "cache" : {
                        "bytes read into cache" : 0,
                        "bytes written from cache" : 863082,
                        "checkpoint blocked page eviction" : 0,
                        "data source pages selected for eviction unable to be evicted" : 0,
                        "hazard pointer blocked page eviction" : 0,
                        "in-memory page passed criteria to be split" : 0,
                        "in-memory page splits" : 0,
                        "internal pages evicted" : 0,
                        "internal pages split during eviction" : 0,
                        "leaf pages split during eviction" : 0,
                        "modified pages evicted" : 0,
                        "overflow pages read into cache" : 0,
                        "overflow values cached in memory" : 0,
                        "page split during eviction deepened the tree" : 0,
                        "page written requiring lookaside records" : 0,
                        "pages read into cache" : 0,
                        "pages read into cache requiring lookaside entries" : 0,
                        "pages requested from the cache" : 10004,
                        "pages written from cache" : 32,
                        "pages written requiring in-memory restoration" : 0,
                        "unmodified pages evicted" : 0
                    },
                    "compression" : {
                        "compressed pages read" : 0,
                        "compressed pages written" : 31,
                        "page written failed to compress" : 0,
                        "page written was too small to compress" : 1,
                        "raw compression call failed, additional data available" : 0,
                        "raw compression call failed, no additional data available" : 0,
                        "raw compression call succeeded" : 0
                    },
                    "cursor" : {
                        "bulk-loaded cursor-insert calls" : 0,
                        "create calls" : 2,
                        "cursor-insert key and value bytes inserted" : 831426,
                        "cursor-remove key bytes removed" : 0,
                        "cursor-update value bytes updated" : 0,
                        "insert calls" : 10000,
                        "next calls" : 101,
                        "prev calls" : 1,
                        "remove calls" : 0,
                        "reset calls" : 10003,
                        "restarted searches" : 0,
                        "search calls" : 0,
                        "search near calls" : 0,
                        "truncate calls" : 0,
                        "update calls" : 0
                    },
                    "reconciliation" : {
                        "dictionary matches" : 0,
                        "fast-path pages deleted" : 0,
                        "internal page key bytes discarded using suffix compression" : 30,
                        "internal page multi-block writes" : 0,
                        "internal-page overflow keys" : 0,
                        "leaf page key bytes discarded using prefix compression" : 0,
                        "leaf page multi-block writes" : 1,
                        "leaf-page overflow keys" : 0,
                        "maximum blocks required for a page" : 31,
                        "overflow values written" : 0,
                        "page checksum matches" : 0,
                        "page reconciliation calls" : 2,
                        "page reconciliation calls for eviction" : 0,
                        "pages deleted" : 0
                    },
                    "session" : {
                        "object compaction" : 0,
                        "open cursor count" : 2
                    },
                    "transaction" : {
                        "update conflicts" : 0
                    }
                },
                "nindexes" : 1,
                "totalIndexSize" : 94208,
                "indexSizes" : {
                    "_id_" : 94208
                },
                "ok" : 1
            }
        },
        "ok" : 1
    }

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    这里写图片描述

    展开全文
  • MongoDB基础篇:MongoDB Shell命令大全

    万次阅读 2019-07-29 18:41:12
    要想能熟练操作MongoDB,首先先要熟练使用 MongoDB Shell, 再次要熟练使用驱动 mongodb-java-driver, 最后是spring-data-mongodb的使用 在使用Shell中的方法时,注意很多方法都是有重载函数的一:启动服务和连接...
    分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

    要想能熟练操作MongoDB,首先先要熟练使用 MongoDB Shell, 再次要熟练使用驱动 mongodb-java-driver, 最后是spring-data-mongodb的使用

    MongoDB 简介:

    MongoDB采用Bson格式存储,BSON格式比JSON数据类型更加丰富,
    支持ObjectId、日期类型、正则表达式、JS代码、二进制数据等

    MongoDB注意:

    • MongoDB 不支持事务
    • MongoDB 不支持多表连接查询
    • MongoDB 中的键值对是有序的,相同的键值对,不同的顺序,属于不同的文档
    • new Date(); 返回日期对象,属于日期类型,Date()函数返回日期字符串,在Shell中操作日期要使用日期类型, 日期类型是包含时区的
    • _id的值可以是任意类型,默认是ObjectId类型,可以在分片环境中生成唯一的标识符(时间戳(单位:秒)+主机的唯一标示(主机名的hash值)+进程标识符PID+自动增加的计数器), 通过时间戳可以大概知道ObjectId大概是按时间先后排序的,主机的唯一标示可以用于保证在多台服务器器上不重复,进程ID为了保证同台服务器器上多个不同的进程之间生成不重复 值,最后一部分是一个自增的计数器, 前面三部分是为了保证同一秒在同一台机器上的同一个进程上生成一个唯一的值,最后一部分用于保证在同一秒、同一台机器、同一个进程 在同一秒内(注意是同一秒内)生成唯一值
    • mongodb中有一些特殊的键,它们被称为修改器、操作符等
    以 $ 开头,如 
    $set(更新字段)、
    $unset(删除字段)、 
    $inc(自增或自减)、
    $and、$or、$in、$nin、$nor、$exists(用于判断文档中是否包含某字段)、
    $push(向数组中尾部添加一个元素)、
    $pushAll(将数组中的所有值push)、
    $addToSet(向set集合中添加元素)、
    $pop(删除数组中的头部或尾部元素), 
    $pull(删除数组中指定的值)、
    $size(根据数组的长度进行筛选)、
    $slice(返回数组中部分元素,如前几个、后几个、中间连续几个元素)、
    $elemMatch(用于匹配数组中的多个条件)、
    $where(自定义筛选条件,效率比较低,需要将bson转为js对象,不能使用索引,可以先使用普通查询过滤掉部分不满足条件的文档,然后再使用where,尽量减少where操作文档的数量过大)
    
    

    MongoDB 与 关系型数据库的对比:

    • MongoDB ----------> SQL
    • database数据库 ---->database数据库
    • collection集合------->table表
    • document文档----> row 行
    • filed字段-------> column列
    • index索引-----> index索引
    • 不支持多表连接查询—> 支持多表连接查询
      在使用Shell中的方法时,注意很多方法都是有重载函数的

    一:启动服务和连接服务

    1、mongod 用于启动MongoDB服务

    MongoDB的数据时存储在磁盘上的,而不是存储在内存中的,所以在启动MongoDB服务时需要指定数据存储的位置, 如果不指定会默认存储在/data/db目录下, 注意在使用默认位置时,需要以管理员身份预先创建好目录

    方式一: 使用默认的路径,MongoDB安装所在的盘符:/data/db

    C:\Windows\system32>D:
    D:\>mkdir data
    D:\>cd data
    D:\data>mkdir db
    D:\data>cd D:\Java\MongoDB\Server\bin
    D:\Java\MongoDB\Server\bin>mongod
    
    MongoDB starting : pid=9712 port=27017 dbpath=D:\data\db\ 64-bit host=zm-PC
    

    这里写图片描述

    方式二: 显式指定数据库路径

    此种方式也要预先创建好目录,这里的位置放置MongoDB里面,如D:\Java\MongoDB\DB,放在MongoDB里面不需要管理员身份创建
    这里写图片描述

    方式三: 安装服务

    D:\Java\MongoDB\Server\bin>mongod  --dbpath=D:\data\db --logappend --logpath=D:\data\log.txt --install
    

    这里写图片描述

    以后启动服务只需要net start MongoDB, 比mongod --dbpath=xxx稍微方便些, 以后电脑开机后就自动启动了,省的每次都要启动

    这里写图片描述


    2、mongo 用于客户端连接服务器

    语法: mongo [IP:PORT][/DATABASE_NAME]

    IP默认的是127.0.0.1
    Port默认的是27017
    database默认的是test,mongodb中默认有两个数据库admin、local

    D:\Java\MongoDB\Server\bin>mongo
    

    这里写图片描述

    D:\Java\MongoDB\Server\bin>mongo 127.0.0.1:27017
    
    D:\Java\MongoDB\Server\bin>mongo 127.0.0.1:27017/admin
    
    // 连接时不指定要连接数据库,需要时从连接中获取需要的数据库
    D:\Java\MongoDB\Server\bin>mongo --nodb
    MongoDB shell version v3.4.6
    > db
    2017-07-27T20:27:25.181+0800 E QUERY    [thread1] ReferenceError: db is not defined :
    @(shell):1:1
    > conn = new Mongo("localhost:27017")
    connection to localhost:27017
    > db = conn.getDB("test")
    test
    >
    

    3. 基本命令

    help命令:如果想知道某个对象下都有哪些函数可以使用help命令,直接使用help会列举出mongodb支持操作,使用db.help()会列举所有db对象所支持的所有操作,使用db.mycoll.help()可以列举所有集合对象对应的操作

    > help
            db.help()                    help on db methods
            db.mycoll.help()             help on collection methods
            sh.help()                    sharding helpers
            rs.help()                    replica set helpers
            help admin                   administrative help
            help connect                 connecting to a db help
            help keys                    key shortcuts
            help misc                    misc things to know
            help mr                      mapreduce
    
            show dbs                     show database names
            show collections             show collections in current database
            show users                   show users in current database
            show profile                 show most recent system.profile entries with time >= 1ms
            show logs                    show the accessible logger names
            show log [name]              prints out the last segment of log in memory, 'global' is default
            use <db_name>                set current database
            db.foo.find()                list objects in collection foo
            db.foo.find( { a : 1 } )     list objects in foo where a == 1
            it                           result of the last line evaluated; use to further iterate
            DBQuery.shellBatchSize = x   set default number of items to display on shell
            exit                         quit the mongo shell
    // 查看所有数据级别的操作
    > db.help()
    // 查看集合级别的操作
    > db.mycoll.help()
    // 列举数据库命令
    > db.listCommands()
    

    查看函数方法的实现或者查看方法的定义(比如忘记函数的参数了)可以通过输入函数名,不带小括号

    > db.foo.update
    function (query, obj, upsert, multi) {
        var parsed = this._parseUpdate(query, obj, upsert, multi);
        ...
    }
    
    // 打印语句
    > print("hello, mongodb")
    hello, mongodb
    >
    
    // 执行js脚本
    D:\Java\MongoDB\Server\bin>mongo script1.js script2.js
    loading file: script1.js
    I am script1.js
    loading file: script2.js
    I am script2.js
    
    // 使用load()函数加载脚本来执行
    > load("script1.js")
    I am script1.js
    true
    
    // script3.js
    print(db.getMongo().getDBs());	  // show dbs
    db.getSisterDB("foo");    // use foo
    db.users.insert({"username": "mengday", "age": 26})
    print(db.getCollectionNames());  // show collections
    
    > load("script3.js")
    [object BSON]
    users
    true
    >
    
    // 使用脚本可以定义一些辅助的工具函数
    tools.js
    var connectTo = function (port, dbname) {
    	if(!port) port = 27017;
    	if(!dbname) dbname = "test";
    
    	db = connect("localhost:" + port + "/" + dbname);
    
    	return db;
    }
    
    > load("tools.js")
    true
    > typeof connectTo
    function
    > connectTo("27017", "admin")
    connecting to: mongodb://localhost:27017/admin
    MongoDB server version: 3.4.6
    admin
    >
    
    客户端启动时自动执行js脚本
    在用户的主目录下(如C:\Users\mengday)下创建一个.mongorc.js文件,该脚本可以做一些操作,如重写shell命令,禁掉一部分功能,如删除数据库,表等危险操作
    // .mongorc.js
    print("--------------MongoDB is started--------------");
    
    var no = function(){
    	print("not permission");
    }
    
    db.dropDatabase = DB.prototype.dropDatabase = no;
    DBCollection.prototype = no;
    DBCollection.prototype.dropIndex = no;
    
    // 启动shell时会自动执行
    D:\Java\MongoDB\Server\bin>mongo
    MongoDB shell version v3.4.6
    connecting to: mongodb://127.0.0.1:27017
    MongoDB server version: 3.4.6
    ----------------MongoDB is started-----------------
    > db
    test
    > db.dropDatabase()
    not permission
    >
    
    // mongo 启动后给EDITOR变量赋值一个文本编辑器的位置,然后就可以使用edit命令来打开编辑某个变量了,编辑后保存,然后直接关掉编辑器即可,这对于一条命令或者变量比较长编辑比较方便,注意文本编辑器的位置不能包含空格,路径要使用/,不能使用\
    EDITOR="D:/SublimeText/sublime_text.exe"
    var user = {"username": "mengday", "nickname": "xxx"};
    edit user
    
    // 方式二:可以将该配置放在.mongorc.js中,以后就不用每次设置了
    EDITOR="D:/SublimeText/sublime_text.exe";
    

    二:数据库基本命令

    这里写图片描述

    查看当前数据库 db
    显示所有数据库 show dbs,如果数据库里没有任何集合,是不展示出来的,如 use test2, show dbs 时是不包含test2数据库的
    切换或者新建数据库 use DATABASE_NAME, 切换数据库时如果数据库不存在,则会创建它
    删除数据库 db.dropDatabase()
    显示所有表(集合)show tables
    查看js方法的原型(源代码实现): db.xxx.insert, 随便写一个集合名字,集合后面跟函数名,不需要函数的参数 即可查看该函数的源码实现

    // mong shell 是一种javascript shell, 可以定义变量、函数,调用函数
    > x = 200
    200
    > x / 5
    40
    > Math.sin(Math.PI / 2)
    1
    // new Date():是创建一个日期对象,而Date()函数是返回日期字符串,注意日期类型数据和字符串数据不是一种数据,MongoDB Shell在操作日期字段的时候是操作的日期类型而不是字符串类型
    > new Date()
    ISODate("2017-07-27T00:18:34.370Z")
    > Date()
    Thu Jul 27 2017 08:18:37 GMT+0800
    >
    > "Hello, World!".replace("World", "MongoDB")
    Hello, MongoDB!
    > function factorial(n) {
    ... if(n <= 1) return 1;
    ... return n * factorial(n - 1);
    ... }
    > factorial(5)
    120
    >
    
    // db 是一个全局变量,存储当前的数据名称,当切换数据库时会自动更改db的值
    > db
    test
    > show dbs
    admin  0.000GB
    local  0.000GB
    > use local
    switched to db local
    > show tables
    startup_log
    > use test
    switched to db test
    > db.dropDatabase()
    { "ok" : 1 }
    > db.xxx.insert
    
    // 查看一个bson的大小,每个文档最大不超过16M
    > var user = {"username": "mengday"}
    > Object.bsonsize(user)
    27
    

    集合操作

    创建集合

    方式一:隐式创建集合
    当向集合中的插入文档时,如果集合不存在,系统会自动创建,所以向一个不存在的集合中插入数据也就是创建了集合

    > db
    test
    > show tables
    > db.users.insert({"usernmae": "mengdee", "age": 26})
    WriteResult({ "nInserted" : 1 })
    > show tables
    users
    >
    

    方式二:显示创建集合
    db.createCollection(“集合名字”, 可选配置)
    显示创建集合可以通过一些配置创建一些特殊的集合,如固定集合

    > show tables
    users
    > db.createCollection("address")
    { "ok" : 1 }
    
    // 固定集合只能通过调用方法显式创建,固定集合可以指定集合存储数据的大小和最多允许存储的条数
    // 当固定集合文档条数达到上限时,再插入新的文档会将最老的文档删除掉,然后插入到该位置
    > db.createCollection("address", {capped: true, size: 10000, max:1000})
    { "ok" : 1 }
    > show tables
    address
    users
    >
    

    删除集合

    db.集合名字.drop()

    > db.address.drop()
    true
    

    查看集合

    show tables和show collections都可以查看当前数据下的集合

    > show tables
    address
    users
    >
    > show collections
    address
    users
    >
    

    添加数据

    
    方式一: insert: _id 会自动创建唯一索引,当id重复的时候会报错
    db.集合名字.insert({})        // 插入一条,返回值中不包含insertedIds
    db.集合名字.insert([{}, {}])  // 批量插入,返回值中不包含insertedIds
    db.集合名字.insertOne(Bson)   // 插入一条,返回值返回插入的insertedId
    db.集合名字.insertMany(Bson)  // 批量插入,返回值中包含insertedIds
    db.集合名字.findAndModify({查询条件}, "update": {需要添加或更新的字段},  "upsert": true });
    
    写入安全:
    	应答模式:插入时会返回成功或者失败
    	非应答模式:插入时没有反馈,即插入有没有成功不知道
    > var user = {"name": "mengdee", "age": 20, "address": "上海市浦东新区张江镇", "create_time": new Da
    te()}
    > db.users.insert(user)
    WriteResult({ "nInserted" : 1 })
    > db.users.find()
    { "_id" : ObjectId("5976ad21670af2aa52ea90df"), "username" : "mengdee", "age" : 26 }
    { "_id" : ObjectId("5976b395670af2aa52ea90e0"), "name" : "mengdee", "age" : 20, "address" : "上海市
    浦东新区张江镇", "create_time" : ISODate("2017-07-25T02:57:04.545Z") }
    
    > var userDoc = db.users.findOne()
    > var insertDate = userDoc["_id"]
    > insertDate.getTimestamp()
    ISODate("2017-07-25T02:29:53Z")
    > insertDate.str
    5976ad21670af2aa52ea90df
    
    > db.users.insertOne({"username": "mengday3"})
    {
            "acknowledged" : true,
            "insertedId" : ObjectId("5976b632670af2aa52ea90e1")
    }
    > db.users.insertMany([{"username": "mengday4"}, {"username": "mengday5"}])
    {
            "acknowledged" : true,
            "insertedIds" : [
                    ObjectId("5976b666670af2aa52ea90e2"),
                    ObjectId("5976b666670af2aa52ea90e3")
            ]
    }
    > db.users.insert([{"username": "mengday6"}, {"username": "mengday7"}])
    BulkWriteResult({
            "writeErrors" : [ ],
            "writeConcernErrors" : [ ],
            "nInserted" : 2,
            "nUpserted" : 0,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "upserted" : [ ]
    })
    
    // 使用insertOne插入重复的_id 会报错
    > db.users.insertOne({"_id": 1, "username": "mengday8"})
    { "acknowledged" : true, "insertedId" : 1 }
    > db.users.insertOne({"_id": 1, "username": "mengday8"})
    2017-07-25T11:15:47.822+0800 E QUERY    [thread1] WriteError: E11000 duplicate key error collection:
     test.users index: _id_ dup key: { : 1.0 } :
    WriteError({
            "index" : 0,
            "code" : 11000,
            "errmsg" : "E11000 duplicate key error collection: test.users index: _id_ dup key: { : 1.0 }
    ",
            "op" : {
                    "_id" : 1,
                    "username" : "mengday8"
            }
    })
    
    // findAndModify 也可以用于插入文档,但是前提是一定不存在,如果存在了就变成更新了,单纯的插入还是不要用种方式了,findAndModify一般用于更新或删除操作
    > db.users.findAndModify({ "query": {"username": "mengday11"}, "update": {"username": "mengday11", "age": 26},  "upsert": true })
    null
    > db.users.find()
    { "_id" : ObjectId("597c584448c373e228a9259e"), "username" : "xxx", "age" : 26 }
    

    MongoDB Shell是一种JS,所以可以通过var来定义变量,可以通过find()方法来查找集合中的所有数据,相当于select * from users
    插入数据时,如果没有指定_id这个字段,系统会自动生成一个值,从该值中能够解析出插入文档的日期或者获取日期中的字符串值

    方式二:save()
    db.集合名字.save(Bson) : 如果要插入的文档没有指定_id,则插入文档,如果指定_id,如果集合中不包含_id,则插入文档,如果集合中已经存在相同的id值,则更会整体替换

    > db.users.find()
    { "_id" : 1, "username" : "mengday8" }
    { "_id" : 2, "username" : "mengday8" }
    > db.users.save({ "_id" : 3, "mengday9" : 20})
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 3 })
    > db.users.save({ "_id" : 2, "age" : 20, "gender": 1 })
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday8" }
    { "_id" : 2, "age" : 20, "gender" : 1 }
    { "_id" : 3, "mengday9" : 20 }
    >
    > db.users.save([{ "_id" : 4, "username": "mengday9"}, { "_id" : 5, "username":"mengday10"}])
    

    方式三: update()
    update({查询条件}, {更新的文档}, 是否开启addOrUpdate) : addOrUpdate为true,当集合中不存在的时候就插入,存在就更新

    > db.users.find()
    { "_id" : 5, "username" : "mengday10" }
    > db.users.update({"username" : "mengday11"}, { "_id" : 6, "age" : 20, "gender" : 1 }, true)
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 6 })
    > db.users.find()
    { "_id" : 5, "username" : "mengday10" }
    { "_id" : 6, "age" : 20, "gender" : 1 }
    >
    

    删除 remove

    remove({删除条件}): 删除满足条件的所有数据
    remove({删除条件}, true): 删除满足条件的第一条数据
    remove({}): 清空集合中的所有文档

    // 删除bson变量中的某个字段
    > var user = {"username": "mengday", "age": 26}
    > delete user.age
    > user
    { "username" : "mengday" }
    
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "password" : "123456" }
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 3, "username" : "mengday3", "password" : "123456", "age" : 18 }
    { "_id" : 4, "username" : "mengday4", "password" : "123456", "age" : 28 }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({age: {$lt: 38}})
    WriteResult({ "nRemoved" : 2 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "password" : "123456" }
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({"password": "123456"}, true)
    WriteResult({ "nRemoved" : 1 })
    > db.users.find()
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({})
    WriteResult({ "nRemoved" : 2 })
    
    // findAndModify可以用来插入或更新upsert、也可以用来删除
    > db.users.findAndModify({
       "query": {"username": "mengday"},
       "remove": true
    })
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "CHAOYANG"
                    }
            ],
            "create_time" : ISODate("2017-07-29T09:09:14.031Z")
    }
    

    更新 update,findAndModify

    更新指定字段的值
    替换整个文档
    更新满足条件的第一条文档
    更新满足条件的所有文档

    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "age" : 38 }
    // 使用$set修改器修改指定字段, 当字段不存在时会创建并赋值
    > db.users.update({"username": "mengday5"}, {$set: {"age": 18}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "age" : 18 }
    
    // $unset 用于删除字段
    > db.users.update({"username": "mengday5"}, {"$unset": {"age": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    // $push: 向数组的尾部添加一个元素,如果字段不存在则创建
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": "mm"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm" ] }
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": "money"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money" ] }
    >
    
    // $push + $each : 批量push
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": {"$each": ["play", "eat"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat" ] }
    >
    
    // $pushAll = $push + $each 批量push
    > db.users.update({"username": "mengday5"}, {"$pushAll": {"hobby": ["drink", "happy"]}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat", "drink", "happy" ] }
    
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    // $addToSet:不重复的set集合
    > db.users.update({}, {"$addToSet": {"hobby": "eat"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
    >
    > db.users.update({}, {"$addToSet": {"hobby": {"$each": ["eat", "drink"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat", "drink" ] }
    >
    
    // $pop: 弹出数组的头部元素或尾部元素: -1:头部,1:尾部
    > db.users.update({}, {"$pop": {"hobby": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
    
    // $pull: 删除数组中的值
    > db.lists.insert({"no": [1, 1, 1, 3]})
    WriteResult({ "nInserted" : 1 })
    > db.lists.update({}, {"$pull": {"no": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.lists.find()
    { "_id" : ObjectId("597c0a3087d089dfa7ce1be2"), "no" : [ 3 ] }
    >
    
    // 使用小标或者定位操作符$来操作数组
    > db.users.find()
    { "_id" : ObjectId("597c3c1587d089dfa7ce1be3"), "username" : "mengday", "addresses" : [ { "city" : "shanghai", "area" : "zhangjiang" }, { "city" : "be
    ijing", "area" : "chaoyang" } ] }
    >
    // 修改内嵌文档数组中第二个元素的值
    > db.users.update({"username": "mengday"}, {"$set": {"addresses.1.area": "chaoyangqu"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "chaoyangqu"
                    }
            ]
    }
    
    // 定位操作符$: 查询条件一般是以数组中的元素为条件,使用$符号作为满足查询条件的第一条文档对应的下标值
    > db.users.update({"addresses.city": "beijing"}, {"$set": {"addresses.$.area": "CHAOYANG"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "CHAOYANG"
                    }
            ]
    }
    
    
    // 文档整体替换
    > db.users.update({"username": "mengday5"}, {"age": 17})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    
    // 第三个参数: 插入或者更新,当_id不存在的时候插入,当_id值存在的时候更新
    > db.users.update({"_id": 2}, {"username": "mengday", "age": 16}, true)
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 2 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    { "_id" : 2, "username" : "mengday", "age" : 16 }
    
    // 更新
    > db.users.update({"_id": 2}, {"username": "mengday2", "birthday": new Date()}, true)
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    { "_id" : 2, "username" : "mengday2", "birthday" : ISODate("2017-07-25T06:33:10.579Z") }
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 16 }
    { "_id" : 2, "username" : "mengday2", "age" : 16 }
    
    // 更新满足条件的第一条文档
    > db.users.update({"age": 16}, {$set: {"age": 18}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 18 }
    { "_id" : 2, "username" : "mengday2", "age" : 16 }
    
    // 第三个参数:insertOrUpdate, 第四个参数:是否批量更新,true就是更新所有满足条件的文档
    > db.users.update({"age": {$gte: 16}}, {$set: {"age": 25}}, false, true)
    WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 25 }
    { "_id" : 2, "username" : "mengday2", "age" : 25 }
    >
    
    // 查询然后更新,更新是整体替换, 如果想更新指定的字段使用$set修改器即可
    > db.users.findAndModify({
        query: { "username": "mengday"},
        update:{
               "age": 20,
                "username": "mengday20"
        }
    })
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    > db.users.find()
    { "_id" : 1, "age" : 20, "username" : "mengday20" }
    

    查询

    // 查询所有, 相当于 select * from users
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    >
    
    // pretty() 用于格式化查询的结果
    > db.users.find().pretty()
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    ...
    {
            "_id" : 5,
            "username" : "sunday",
            "age" : 37,
            "birthday" : ISODate("2017-07-25T07:07:45.420Z")
    }
    >
    
    // 查询一条, 相当于select * from users limit 1
    > db.users.findOne()
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    
    // 查询条件, 相当于 select * from users where age < 20
    > db.users.find({"age": {$lt: 20}})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    
    // 查询指定的字段,1:代表要查询的字段,0:代表不要查询的字段 ,相当于 select username, age from users where age < 20
    > db.users.find({"age": {$lt: 20}}, {"_id":0, "username": 1, "age": 1})
    { "username" : "tom", "age" : 18 }
    
    // and 条件,多个调剂直接用逗号分开,不需要什么操作符: 相当于 select * from users where age < 20 and id < 3
    > db.users.find({"age": {$lt: 30}, "_id": {$lt: 3 }})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    
    // 同一个字段多个条件: 相当于 select * from users where age > 25 and age < 30
    > db.users.find({"age": {$gt: 25, $lt:30 }})
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    // or: 相当于 select * from users where age > 30 or username = 'tom'
    > db.users.find({$or: [{"age": {$gt: 30}}, {"username": "tom"}]})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    
    // and or 混合使用,相当于 select * from users where id < 4 and (username = 'mengdat' or age < 20)
    > db.users.find({ $or: [{"username": "mengday"}, {"age": {$lt: 20}}], "_id": {$lt: 4} })
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    >
    
    // in: 相当于 select * from users where age in (18, 28)
    
    > db.users.find({"age": {$in: [18, 28]}})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    >
    
    // 正则表达式不但可以匹配字符串还可以匹配字段值是正则表达式类型的,此时是相等匹配
    // 模糊查询,正则表达式: 以xiao开头,以ng结尾
    // 相当于 select * from users where username like 'xiao%' and username like '%ng'
    > db.users.find({"username": /^xiao/, "username": /ng$/})
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    > db.users.insert({"_id": 6, "username": "sunday", "age": 39, "birthday": new Date(), "hobby": ["eat
    ", "drink", "play", "happy", "money", "mm"] })
    WriteResult({ "nInserted" : 1 })
    
    // 正则表达式忽略大小写
    > db.users.find({"username": {$regex:/sunday/, $options:"$i"}})
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 正则表达式用于数组
    > db.users.find({"hobby": {$regex: "mm"}})
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 正则表达式包含变量时需要使用eval()函数来计算
    > var username = "sunday"
    > db.users.find({"username": {$regex:eval("/" + username + "/i")}})
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 数组字段: 值,意思就是这个数组中是否包含该元素,如果包含就是满足条件的
    > db.food.insert({"fruit": ["apple", "banana", "cherry"]})
    WriteResult({ "nInserted" : 1 })
    > db.food.find({"fruit": "banana"})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    // 当值是一个值时是是否包含,当值是数组时就是精确匹配了,此时匹配不到结果
    > db.food.find({"fruit":  ["apple", "cherry"]})
    // $all: 数组中同时都包含多个元素
    > db.food.find({"fruit": {$all: ["apple", "cherry"]}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    // 查询数组中指定的下标对应的值是否和给的值一样
    // 查询文档中的fruit中第三个元素的值是cherry的文档
    > db.food.find({"fruit.2": "cherry"})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    >
    
    // $size: 根据数组的长度进行筛选
    > db.food.find({"fruit": {$size: 3}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    
    > db.food.find()
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "orange", "cherry" ]
    >
    // 返回数组中前两个元素
    > db.food.find({}, {"fruit": {$slice: 2}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana" ] }
    // 返回数组中后两个元素
    > db.food.find({}, {"fruit": {$slice: -2}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "orange", "cherry" ] }
    // 偏移下标为1,取2个长度,相当于 limint 0, 2
    > db.food.find({}, {"fruit": {$slice: [1, 2]}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "banana", "orange" ] }
    >
    
    
    > db.test.find()
    { "_id" : ObjectId("597d4342e210addac88b2a37"), "x" : [ 2, 5 ] }
    { "_id" : ObjectId("597d4350e210addac88b2a38"), "x" : [ 4, 5 ] }
    { "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
    // $elemMatch: 数组中是否有一个元素同时满足所有条件(只要有一个元素满足就能匹配上)
    > db.test.find({"x": {"$elemMatch": {$gt: 5, $lt: 20}}})
    { "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
    
    // 根据字段的数据类型来查询,2代码String
    > db.users.find({"username": {$type: 2}})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 查询文档中没有username字段的或者username的值是null
    > db.users.find({"username": null})
    // 查询文档中存在username字段,并且值是null, $in:[null]和username:null 一样的效果
    > db.users.find({"username": {$in: [null], $exists: true}})
    { "_id" : ObjectId("597c58f848c373e228a925a6"), "username" : null, "age" : 25 }
    { "_id" : ObjectId("597c591e48c373e228a925ab"), "username" : null, "age" : 24 }
    
    // 自定义筛选条件,通过js函数返回的boolean值来筛选,可以实现复杂条件的筛选
    > db.users.find({$where: function(){ return this.username == 'mengday' }})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    
    // 运行命令: 平常使用的很多命令如db.test.drop()底层都是调用的db.runCommand({"函数名":参数值})来实现的
    > db.runCommand({"drop": "test"})
    { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1 }
    // db.getLastError 和 db.runCommand({getLastError: 1}) 是一样的
    > db.getLastError
    > db.runCommand({getLastError: 1})
    
    ### 游标
    
    游标: 将查询结果赋值给一个局部变量,这个局部变量就是游标, 使用游标时shell并不理解查询数据库,而是等待真正开始要求获取结果时(调用hasNext()或者next()方法)才发送查询,这样在执行之前可以给查询附加额外的选项,如skip、limit、sort等,游标是一次性的,即用过一次即销毁
    

    var cursor = db.users.find()
    while(cursor.hasNext()){
    user = cursor.next();
    print(user);
    }

    // 需要重新查新赋值一个游标,上一个游标已经销毁

    var cursor = db.users.find()
    cursor.forEach(function(x){
    print(x);
    });

    // 查询两条文档 , 相当于 select id, username from users limit 2

    db.users.find({}, {“username”: 1}).limit(2)
    { “_id” : 1, “username” : “mengday” }
    { “_id” : 2, “username” : “tom” }

    // 分页第一种方法使用skip和limit函数, skip(2) 是指的offset, 相当于 select id, username from users limit 2,2

    db.users.find({}, {“username”: 1}).skip(2).limit(2)
    { “_id” : 3, “username” : “xiaohong” }
    { “_id” : 4, “username” : “xiaoming” }

    // sort 排序, 1:升续, 2:降续

    db.users.find({}, {“username”: 1}).skip(2).limit(2).sort({“age”: 1})
    { “_id” : 4, “username” : “xiaoming” }
    { “_id” : 3, “username” : “xiaohong” }

    // 分页第二种方法:使用sort和limit函数

    db.users.find()
    { “_id” : 1, “username” : “mengday1”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:33.837Z”) }
    { “_id” : 2, “username” : “mengday2”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:43.021Z”) }
    { “_id” : 3, “username” : “mengday3”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:53.420Z”) }
    { “_id” : 4, “username” : “mengday4”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:00.299Z”) }
    { “_id” : 5, “username” : “mengday5”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:07.826Z”) }
    { “_id” : 6, “username” : “mengday6”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:13.290Z”) }
    { “_id” : 7, “username” : “mengday7”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:54:36.710Z”) }
    { “_id” : 8, “username” : “mengday8”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:54:40.262Z”) }

    // 先根据日期进行排序,获取第一页数据时直接使用limit指定获取的条数,将结果赋值给局部变量,然后循环该游标,记录下最后一条文档对应的日期值

    var page1 = db.users.find().sort({“create_date”: 1}).limit(5);
    var latest = null;
    while(page1.hasNext()){
    … latest = page1.next();
    … print(“page1:” + latest.username);
    … }
    page1:mengday1
    page1:mengday2
    page1:mengday3
    page1:mengday4
    page1:mengday5

    // 获取后面的页:将上一页保存的文档对应的时间作为下一页查询的条件,因为还好对时间进行排序,又过滤掉之前的数据,相当于skip的效果,然后再获取指定的条数

    var page2 = db.users.find({“create_date”: {$gt: latest.create_date}}).sort({“create_date”: 1}).limit(5);
    while(page2.hasNext()){
    … latest = page2.next();
    … print(“page2:” + latest.username);
    … }
    page2:mengday6
    page2:mengday7
    page2:mengday8

    
    ### 聚合操作
    
    

    // distinct: 查询某个字段的所有不重复的值, 相当于 select distinct age from users

    db.users.distinct(“age”)
    [ 20, 18, 28, 27, 37, 39 ]

    
    // 分组: key: 要分组的字段, initial:值的初始化, condition:是筛选条件,$reduce:将满足的条件的所有文档都会执行该函数,finalize:每组函数执行完之后的操作,可以做一些统计什么的
    db.users.group({ 
    	"key": {"age": true}, 
    	"initial": {"user": []}, 
    	"$reduce": function(cur, prev){
    						prev.user.push(cur) ;
    			   },
    	"condition": {"age": {$lt:25}},
    	"finalize": function(out) {
    		out.count = out.user.length;
    	}
    })
    
    [
            {
                    "age" : 20,
                    "user" : [
                            {
                                    "_id" : 1,
                                    "age" : 20,
                                    "username" : "mengday20"
                            }
                    ],
                    "count" : 1
            },
            {
                    "age" : 18,
                    "user" : [
                            {
                                    "_id" : 2,
                                    "username" : "tom",
                                    "age" : 18,
                                    "birthday" : ISODate("2017-07-25T07:05:52.166Z")
                            }
                    ],
                    "count" : 1
            }
    ]
    >
    
    
    
    分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

    官方文档: https://docs.mongodb.com/manual/reference/method/

    展开全文
  • MongoDB实战之---初级篇

    万人学习 2018-11-27 10:25:02
    本课程环境:MongoDB 3.4.x CentOS 7.x 本课程为初级课程,围绕高阶聚合函数的使用、索引的介绍及原理解析、索引优化、性能优化、副本集搭建及分布式分片集群的搭建和原理解析来对MongoDB进行更深入的学习。...
  • MongoDB数据库从入门到精通

    千人学习 2019-12-18 15:11:50
    本课程是MongoDB数据库的精讲课程,课程从环境搭建开始详细讲述了MongoDB的各个方面,内容涵盖:Mongo shell、数据库CRUD、聚合、索引、数据库模型、MongoDB Java开发和MongoDB Python开发。
  • MongoDB查询

    万次阅读 2019-07-11 00:24:02
    MongoDB查询 查询指定集合的所有文档 db.集合名称.find() 根据条件查询 db.集合名称.find({“属性1” : “值1”, “属性2” : “值2”}) 模糊查询,使用正则表达式 返回指定的键值 ...db....

    MongoDB查询

    查询指定集合的所有文档

    db.集合名称.find()

     

    根据条件查询

    db.集合名称.find({“属性1” : “值1”, “属性2” : “值2”})

     

    模糊查询,使用正则表达式

     

    返回指定的键值

    db.集合名称.find({“查询条件1”: “值1”}, {“属性1” : 1, “属性2” : 1}),第二个参数,属性1的值为1,表示需要显示这个值。如果为0,表示不显示这个值,注意不要1和0混合使用。

     

    范围查询,大于$gt,大于等于$gte,小于$lt,小于等于$lte

    db.集合名称.({“属性1” : {“$gte” : 18, “$lte” : 30}})

     

    不等于查询$ne

    db.集合名称.find(“name” : {$ne : “rose”})

     

    多个值匹配$in

     

    多个值不匹配$nin

     

    Null

    这样的查询是没有效果的

    $exists:true,确定存在该键。$in:[null],值为null

     

    查询数组

    这样查询,整个匹配的数据才返回。

    $all只要一个匹配就返回

    查询指定的长度,只有长度是2的才返回。

     

    Limit,返回指定的条数

     

    Skip跳过前面多少条数据

     

    Sort排序,1正序,-1倒序

     

    布尔值运算

    $ne在上面已经有案例,这里不多介绍

     

    $not条件取反

    如果是mysql的语句,可以理解为查询NULL的值,我们使用IS NULL 和NOT IS NULL来表示数据库的值是否为NULL,$not效果是一样的

    $lte查询小于等于19岁的,但是使用了$not就表示查询大于19岁的用户。

     

    $or或者查询

    只要数组中的一个条件满足就可以了,由于比较简单,这里给案例就好了。$nor就是$or的相反而已,所有条件都不匹配,您可以自己尝试去写一下查询条件。

     

    $and一致查询,这个就是全部条件都要满足才可以返回数据

     

    $exists,判断属性是否存在

    查询用户存在emails属性的用户,即使是null也可以

     

    $where,javascript查询运算符

    通常,可能我们的查询语句非常复杂,这样无法满足我们的要求的时候,可以自定义javascript函数来作为查询

    例如,我们要查询明年年龄是19岁的用户,那么就可以使用函数,将年龄 + 1 == 19

     

    $slice选择返回文档的子集

    例如用户的爱好有很多,但是只需要返回前面的2个即可。

    或者需要返回第二和第三个爱好,slice有2个参数。

    返回最后2个爱好,使用负数

    关注微信公众号(程序员小兔)不定期分享技术

    展开全文
  • MongoDB逻辑操作符$or, $and,$not,$nor

    万次阅读 2017-07-14 15:56:21
    $or是一个逻辑or操作符操作在一个数据或者多个表达式并且需要选择至少一个满足条件的表达式,$or有至少以下表达式: { $or: [ { expression1> }, { expression2> }, ......考虑下面的例子: ...
  • MongoDB是什么?看完你就知道了

    万次阅读 多人点赞 2019-09-03 14:18:19
    最近在回顾mongodb的相关知识,输出一篇文章做为MongoDB知识点的总结。 总结的目的在于回顾MongoDB的相关知识点,明确MongoDB在企业级应用中充当的角色,为之后的技术选型提供一个可查阅的信息简报 ...
  • mongodb复杂条件查询 (or与and)

    万次阅读 多人点赞 2018-06-08 11:44:40
    使用Mongodb查询需要拼接复杂的or和and参数MongoDb有表格:1"state1" : 11,"state2" : 21,"value" : 1002"state1" : 11,"state2" : 22,"...
  • Mongo入门(一)

    千次阅读 2018-05-31 21:21:00
    一:为什么要用mongo1.MongoDB与MySQL的区别 2.MongoDB适用于什么场景 MongoDB 的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS 系统(具有丰富的功能)之间架起一座桥梁,它集两者的优势...
  • // mongotest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // create by sunqicai, 2019-01-24 #include "pch.h" #include &lt;iostream&...bsoncxx/buil...
  • PyCharm配置mongo插件

    万次阅读 多人点赞 2017-09-01 21:07:16
    转载来自: ... 一、安装mongo plugs插件 File->Setting Plugins查询Mongo选择Search in repositories 选择Mongo plugins,选择install 然后重启pycharm,Restart PyCh
  • mongotemplate 多表多条件查询记录

    万次阅读 2019-04-04 14:54:57
    mongotemplate 多表多条件查询记录 在这里插入代码片
  • mongo重启命令

    万次阅读 2017-12-26 15:58:12
    1.查看mogon连接情况: mongo
  • mongodb精简教程

    万人学习 2018-10-22 21:38:04
    剔除繁杂的理论,注重实践,深入浅出讲解nosql数据库mongodb
  • MongoTemplate用法笔记

    万次阅读 2018-01-29 15:46:50
    1.前言 代码中的Object代表数据库...2.导入Mongo相关jar包 dependency> groupId>org.mongodbgroupId> artifactId>mongo-java-driverartifactId> version>3.5.0version> dependency> dependency> groupId>or
  • 转载自:http://www.akaros.cn/blog/mongo-%E6%8A%A5connectsrcmongoshellmongojs25113%E9%94%99%E8%AF%AF%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F/ ... 一般情况mongo默认的数据文件的在/data/d...
  • MongoTemplate 联合查询

    2017-04-01 03:06:27
    mongo 有没有 类似MySQL的那种多表查询??望指教,万分感谢
  • MongoTemplate查询内嵌子文档如何查询?![](https://gss0.baidu.com/-fo3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/b17eca8065380cd78f44d231a744ad3458828197.jpg)
  • mongo update批量更新

    万次阅读 2018-03-06 10:50:13
    参考链接 https://docs.mongodb.com/manual/reference/method/db.collection.update/findAndModify只会更新一个, update可以批量更新db.getCollection('cuishou_user').update( {'id':{$in:[1,2,3,10,12,13]}}, //...
1 2 3 4 5 ... 20
收藏数 95,143
精华内容 38,057
关键字:

mongo