MongoDB 安装、命令、Robo3T、与SQL语法对比

MongoDB 官网下载地址:https://www.mongodb.com/try/download/community
MongoDB 中文手册:https://mongodb.net.cn/manual/reference/configuration-options/
MongoDB 教程:https://www.runoob.com/mongodb/mongodb-relationships.html

一、MongoDB 简介、安装

NoSQL,全称为 Not Only SQL,意为不仅仅是 SQL,泛指非关系型数据库。NoSQL 是基于键值对的,而且不需要经过 SQL 层的解析,数据之间没有耦合性,性能非常高。

非关系型数据库又可细分如下

  • 键值存储数据库:代表有Redis、Voldemort 和 Oracle BDB等
  • 列存储数据库:代表有Cassandra、HBase和Riak等。
  • 文档型数据库:代表有CouchDB和MongoDB等。
  • 图形数据库:代表有 Neo4J、InfoGrid 和I finite Graph 等。

对于爬虫的数据存储来说,一条数据可能存在因某些字段提取失败而缺失的情况,而且数据可能随时调整。另外,数据之间还存在嵌套关系。如果使用关系型数据库存储这些数据,一是需要提前建表,二是如果数据存在嵌套关系,还需要进行序列化操作才可以存储,这非常不方便。如果使用非关系型数据库,就可以避免这些麻烦,更简单、高效。

MongoDB 简介

MongoDB 是由C++语言编写并基于分布式文件存储的开源数据库,属于NOSQL 。

MongoDB 是一款介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的 NOSQL 数据库。它面向文档存储,而且安装和操作起来都比较简单和容易,而且它支持各种流行编程语言进行操作,如Python,Node.js,Java,C++,PHP,C#等。

目前在大数据、内容管理、持续交付、移动应用、社交应用、用户数据管理、数据中心等领域皆有广泛被使用。

MongoDB 相对于 RDBMS 的优势

  • 无固定结构 。
  • 数据结构由键值(key=>value)对组成。MongoDB 的文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组,单个对象的结构是清晰的。
  • 没有复杂的表连接。不需要维护表与表之间的内在关联关系。
  • 查询功能强大。MongoDB的查询功能几乎与SQL一样强大,使用基于文档的查询语言,可以对文档进行动态查询。
  • 易于调优和扩展。具备高性能、高可用性及可伸缩性等特性
  • 应用程序对象与数据库对象天然对应。
  • 可以基于内存存储或者硬盘文件存储,提供丰富的查询操作和索引支持,也有事务操作,可以更快地更稳定的访问数据。

MongoDB 是一款非常热门的 NoSQL 面向文档的数据库管理系统, 分为 企业版收费版社区免费版。MongoDB 使用 BSON 对象来存储,与 JSON 格式类型的 "键 - 值" 对( key / value )类似,MongoDB 数据库和关系型DB的存储模型对应关系:

SQLMongodb描述
库( database )库( database )
表( Table )集合( Collection )
行/记录( Row )文档( Document )Document 就是 json 结构的一条数据记录
列/字段( Col )字段 / 键 / 域( Field )
主键( Primary Key )对象 ID( ObjectId )_id: ObjectId("10c191e8608f19729507deea")
索引( Index )索引( Inde x)也有普通索引, 唯一索引这么区分的

MongoDB 安装

官网安装文档:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

mongodb 镜像 下载:https://mirrors.tuna.tsinghua.edu.cn/help/mongodb/

社区版 下载:https://www.mongodb.com/try/download/community

安装方式有两种:

  • 方式 1:下载安装包,直接安装,这种安装方法会有一个默认的配置文件,启动时候会读取
  • 方式 2:下载压缩包直接解压,bin 目录下直接执行。这种的没有配置文件,需要手动创建

在 Windows 中,默认的安装文件存储目录是:C:\Program Files\MongoDB\Server\4.4\bin,点击 Windows+R,输入 cmd,启动 Command Prompt,进入到安装目录:

安装完之后,如果不想每次启动都进入到 bin 目录下,可以设置 环境变量

每次打开 Command Prompt 都需要进入到 MongoDB 的安装目录十分麻烦,可以修改系统环境变量,在 Path 变量的字符串后面追加 ";;C:\Program Files\MongoDB\Server\4.4\bin;;",注意两个Path之间以 英文的分号 ";分割。

数据库 管理 工具

https://www.mongodb.com/try/download/database-tools

下载后直接解压,进入 bin 目录执行即可

  • bsondump:将 bson 格式的文件转储为 json 格式的数据。
  • mongodump:备份 MongoDB 数据。可以导出所有数据到指定目录中。
    示例:./mongodump --uri="mongodb://127.0.0.1:27017/db_prd" -o /data/mongo_db/
  • mongoexport:把一个 collection导出成JSON格式或CSV格式的文件。可以通过参数指定导出的数据项,也可以根据指定的条件导出数据。
  • mongofiles:GridFS 管理工具,可实现二制文件的存取
  • mongoimport:把一个特定格式文件中的内容导入到指定的collection中。该工具可以导入JSON格式数据,也可以导入CSV格式数据。
  • mongorestore:恢复备份的数据。
    示例:mongorestore.exe /uri mongodb://127.0.0.1:27017 /db db_prd /dir db_local
            db_prd:要使用的数据库
            db_local:备份数据所在的目录
  • mongostat:状态检测工具
  • mongotop:用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。

详细说明

linux 安装后的配置

mongodb 4.0 配置:https://www.cnblogs.com/jasonLiu2018/p/13088971.html

Linux上 Mongodb 6.0及以上的版本没有 mongo 命令解决方案

当启动服务时
        ./mongod -f mongodb.conf  #./mongod --config mongodb.conf 
         #进入数据库
        ./mongocd  6.0之前的版本才有这个命令,如果使用./mongocd 或 mongo命令 无法使用的话,那么就证明一件事情,那就是你的版本过高,去掉了mongocd命令

解决方案
安装 mongodb shell
下载安装包:https://www.mongodb.com/try/download/shell
下载成功后解压,为了方便,这里直接解压到 mongodb/bin/MongoShell目录
将 bin 目录添加到 Path 中 
通过编辑文件 vim /etc/profile 添加bin到path中
然后执行source /etc/profile 命令,使刚才的配置生效:
执行 mongosh 命令连接服务即可

mongodb.cfg 配置文件

注意:配置件缩进需要使用tab键(根据自己安装的路径来配置)YAML 不支持使用制表符进行缩进:请使用空格。

YAML(YAML Ain't Markup Language)是一种用于表示数据序列化的格式,它旨在成为一种易读且易于写的格式。YAML 文件通常用于配置文件、数据传输和存储以及其他情境中。
以下是一些基本的 YAML 文件格式规则:

  • 缩进:YAML 使用缩进来表示数据结构,通常使用空格来进行缩进,而不是制表符。缩进的空格数可以是 2 个或 4 个,但在同一个文件中应该保持一致。
  • 注释:使用 # 符号表示注释,# 后面的内容将被视为注释而不被解析为数据。
  • 键值对:使用冒号 : 将键和值分隔开。例如:key: value
  • 列表:使用连字符 - 表示列表中的每个元素。
  • 嵌套结构:YAML 支持嵌套的数据结构,可以使用缩进来表示不同层级的关系。
  • 引号:字符串值可以使用单引号或双引号括起来,尤其是当字符串中包含特殊字符时

这些是 YAML 文件的一些基本格式规则。YAML 还支持更复杂的数据结构,如映射、多行字符串等。使用这些简单规则可以轻松地编写和阅读 YAML 文件。

MongoDB修改最大连接数:https://www.cnblogs.com/boyane/p/17260772.html

mongod.conf 内容如下 

# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/

#storage:
#    dbPath: db27017
#storage:
#    journal:
#        enabled: true

storage:
    dbPath: /usr/local/mongodb-linux-x86_64-ubuntu2004-6.0.7/db
    journal:
        enabled: true
    engine: wiredTiger

systemLog:
    destination: file
    logAppend: true
    path: /usr/local/mongodb-linux-x86_64-ubuntu2004-6.0.7/log/mongodb.log

net:
    bindIp: 0.0.0.0
    port: 27017
    maxIncomingConnections: 1000

processManagement:
    fork: true

security:
  authorization: enabled    

MongoDB 的可视化工具

1,推荐 Robomongo:Robomongo 是开源,免费的MongoDB管理工具,之前叫 Robomongo,后面被收购了,改名 Robo 3T 。下载地址:https://robomongo.org

2,MongoBooster:支持MongoDB 3.2 版本,个人使用免费,用于商业收费,下载地址:http://mongobooster.com/downloads%20

MongoDB Compass 简易教程

MongoDB Compass是MongoDB官网提供的一个集创建数据库、管理集合和文档、运行临时查询、评估和优化查询、性能图表、构建地理查询等功能为一体的MongoDB可视化管理工具。

https://blog.csdn.net/mrjkzhangma/article/details/90082178

二、使用 MongoDB 命令

启动 MongoDB 实例:mongod.exe -f mongod.cfg

环境变量设置成功之后,在C盘中创建一个文件夹data,用于存储 MongoDB 的数据库文件。然后,打开一个命令行工具,输入mongod 启动 MongoDB 实例,默认监听的 TCP 端口是 27017,在浏览器中输入:http://127.0.0.1:27017/ 会显示下面一行英文:It looks like you are trying to access MongoDB over HTTP on the native driver port.

  • mongod 是整个 MongoDB 最核心的进程,负责数据库的创建,删除等管理操作,运行在服务器端,监听客户端的请求,提供数据服务。
  • mongo 进程是构造一个Javascript Shell,用于跟 mongod 进程交互,根据 mongod 提供的接口对MongoDB 数据库进行管理,相当于 SSMS(SQL Server Management Studio),是一个管理MongoDB 的工具。

mongod 命令常用参数

mongod 是 MongoDB 系统的主要守护进程,用于处理数据请求,数据访问和执行后台管理操作,必须启动,才能访问 MongoDB 数据库。

在启动 mongod 时,常用的参数是:

  • --dbpath :存储MongoDB数据文件的目录
  • --directoryperdb:指定每个数据库单独存储在一个目录中(directory),该目录位于--dbpath指定的目录下,每一个子目录都对应一个数据库名字。Uses a separate directory to store data for each database. The directories are under the --dbpath directory, and each subdirectory name corresponds to the database name.
  • --logpath :指定mongod记录日志的文件
  • --fork:以后台deamon形式运行服务
  • --journal:开始日志功能,通过保存操作日志来降低单机故障的恢复时间
  • --config(或-f):配置文件,用于指定runtime options
  • --bind_ip :指定对外服务的绑定IP地址
  • --port :对外服务窗口
  • --auth:启用验证,验证用户权限控制
  • --syncdelay:系统刷新disk的时间,单位是second,默认是60s
  • --replSet :以副本集方式启动mongod,副本集的标识是setname

mongo、mongosh 命令

 Mongodb 6.0及以上的版本没有 mongo,需要安装 mongodb shell。

下载安装包:https://www.mongodb.com/try/download/shell

mongo ( 或者 mongosh ) 是一个交互式的 js shell,提供了一个强大的 js 环境,为 DBA 管理 MongoDB,developer查询 MongoDB 数据提供接口。通过 mongo shell 和 MongoDB 进行交互,查询和修改 MongoDB 数据库,管理 MongoDB 数据库,维护 MongoDB 的副本集和分片集群,是一个非常强大的工具。

在启动 mongo shell时,常用的参数是:

  • --nodb :阻止 mongo 在启动时连接到数据库实例;
  • --port :指定 mongo 连接到 mongod 监听的TCP端口,默认的端口值是 27017;
  • --host :指定 mongod 运行的 server,如果没有指定该参数,那么 mongo 尝试连接运行在本地(localhost)的 mongod 实例;
  • :指定 mongo 连接的数据库
  • --username/-u 和 --password/-p :指定访问 MongoDB 数据库的账户和密码,只有当认证通过后,用户才能访问数据库;
  • --authenticationDatabase :指定创建 User 的数据库,在哪个数据库中创建 User时,该数据库就是 User 的 Authentication Database;

执行命令,进入交互终端: mongo  或者 mongosh

基本操作  help

    db.help()                   显示 db 命令的帮助
    db.mycoll.help()             显示 对应 collection 的帮助
    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                    查看日志

    db.getMongo()             查看当前db的连接机器地址

    db.serverStatus()          当前服务器状态
    show log [name]              prints out the last segment of log in memory, 'global' is default
    use <db_name>                set current database
    db.mycoll.find()             list objects in collection mycoll
    db.mycoll.find( { a : 1 } )  list objects in mycoll 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                        退出 mongo shell

db.serverStatus()

{
    "host" : "ubuntu",    # 主机名
    "version" : "4.4.2",  # mongodb版本
    "process" : "mongod", # mongodb进程,主要有mongod和mongos(分片集群中)两种
    "pid" : NumberLong(1034),  # mongod的pid进程号,可以在linux终端下使用命令 pidof mongod 验证
    "uptime" : 105063,    # mongod服务启动的秒数
    "uptimeMillis" : NumberLong(105063193), # mongod服务启动的毫秒数
    "uptimeEstimate" : NumberLong(105063),  # mongod内部自己计算的启动秒数
    "localTime" : ISODate("2020-12-08T16:01:08.230Z"), # 本地时间,相当于 python的 datetime
    # 连接数相关 
    "connections" : {
        "current" : 1,  # 当前连接数
        "available" : 51199, # 可用连接数
        "totalCreated" : 1,  # 截止目前为止总共创建的连接数
        "active" : 1,   # 还在活跃的连接数

    },

    "globalLock" : {  # 全局锁相关信息
        "totalTime" : NumberLong("105063115000"), # mongod启动后到现在的总时间,单位微秒
        "currentQueue" : { # 当前等待锁队列
            "total" : 0,   # 当前全局锁的等待个数
            "readers" : 0, # 当前全局读锁等待个数
            "writers" : 0  # 当前全局写锁等待个数
        },
        "activeClients" : {
            "total" : 0,   # 当前活跃客户端的个数
            "readers" : 0, # 当前活跃客户端中进行读操作的个数
            "writers" : 0  # 当前活跃客户端中进行写操作的个数
        }
    },

    "network" : { # 网络相关
        "bytesIn" : NumberLong(1611),    # 数据库接收到的网络传输字节数
        "bytesOut" : NumberLong(51269),  # 从数据库发送出去的网络传输字节数
        "numRequests" : NumberLong(16),  # mongod接收到的总请求次数
        
    },
    
    # 操作计数器
    "opcounters" : {
        "insert" : NumberLong(0),  # 本次mongod实例启动至今收到的插入操作总数 
        "query" : NumberLong(287), # 本次mongod实例启动至今收到的查询总数。
        "update" : NumberLong(0),  # 本次mongod实例启动至今收到的更新操作总数 。
        "delete" : NumberLong(0),  # 本次mongod实例启动至今的删除操作总数。
        "getmore" : NumberLong(0), # 本次mongod实例启动至今“getmore”操作的总数。
        "command" : NumberLong(588)# 本次mongod实例启动至今向数据库发出的命令总数 。
    },

    # 存储引擎,是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上
    # MongoDB 支持多种不同的存储引擎(Storage Engine),MongoDB支持的存储引擎有:WiredTiger,MMAPv1和In-Memory。
    # 1. WiredTiger,将数据持久化存储在硬盘文件中;从MongoDB 3.2 版本开始,成为MongDB默认存储引擎
    # 2. In-Memory,将数据存储在内存中
    # 3. MMAPv1,将数据持久化存储在硬盘文件中;
    # WiredTiger是比MMAPv1更好用,更强大的存储引擎,WiredTiger的写操作会先写入缓存(Cache)中,并持久化到WAL(Write ahead log,写日志),每60s或日志文件达到2GB时会做一次Checkpoint(检查点),将当前数据进行持久化,产生一个新的快照。Wiredtiger连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性。
    # Checkpoint,检测点。将内存中的数据变更冲刷到磁盘中的数据文件中,并做一个标记点。
    #             表示此前的数据表示已经持久存储在了数据文件中,此后的数据变更存在于内存和日志中.
    #             是一种让数据库redo(重做)和data(数据)文件保持一致的机制。
    #             并非Mongodb独有的,mysql中的InnoDB也有。

    "storageEngine" : {
        "name" : "wiredTiger", 
        "supportsCommittedReads" : true,
        "oldestRequiredTimestampForCrashRecovery" : Timestamp(0, 0),
        "supportsPendingDrops" : true,
        "dropPendingIdents" : NumberLong(0),
        "supportsTwoPhaseIndexBuild" : true,
        "supportsSnapshotReadConcern" : true,
        "readOnly" : false,
        "persistent" : true,
        "backupCursorOpen" : false
    },
    

    "transactions" : { # 事务,mongodb4.0以后新增特性
        "retriedCommandsCount" : NumberLong(0),
        "retriedStatementsCount" : NumberLong(0),
        "transactionsCollectionWriteCount" : NumberLong(0),
        "currentActive" : NumberLong(0),
        "currentInactive" : NumberLong(0),
        "currentOpen" : NumberLong(0),
        "totalAborted" : NumberLong(0),
        "totalCommitted" : NumberLong(0),
        "totalStarted" : NumberLong(0),
        "totalPrepared" : NumberLong(0),
        "totalPreparedThenCommitted" : NumberLong(0),
        "totalPreparedThenAborted" : NumberLong(0),
        "currentPrepared" : NumberLong(0)
    },
    "locks":{ # 锁相关
    
    },
    "mem" : { # 内存相关
        "bits" : 64, # 操作系统位数
        "resident" : 18,  # 物理内存消耗,单位:M
        "virtual" : 1566, # 虚拟内存消耗
        "supported" : true # 是否显示额外的内存信息
    },
}

数据备份、恢复

MongdoDB 共提供了4个命令工具给我们对数据进行备份与恢复以及导入与导出数据。

数据备份:mongodump -h dbhost -d dbname -o dbdirectory

数据恢复:mongorestore -h dbhost -d dbname --dir dbdirectory

数据导出:mongoexport -d dbname -c collectionname -o file --type json/csv -f field

数据导入:mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f field

shell 命令 

MongoDB 中文手册https://www.mongodb.org.cn/manual/administration/

集合 方法

方法名描述
db.collection.aggregate()聚合,主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果
db.collection.bulkWrite()批量写入
db.collection.createIndex()创建一个集合索引
db.collection.count()返回集合总数或匹配查询的结果集总数
db.collection.deleteOne()删除集合中的一个文档
db.collection.deleteMany()删除集合中的多个文档
db.collection.dataSize()返回集合的大小
db.collection.distinct()返回具有指定字段不同值的文档(去除指定字段的重复数据)
db.collection.dropIndex()删除一个集合中的指定索引
db.collection.dropIndexes()删除一个集合中的所有索引
db.collection.drop()删除当前数据库中的collection集合
db.collection.explain()返回各种方法的查询执行信息
db.collection.ensureIndex()已过时,现使用db.collection.createIndex()
db.collection.findOne()查询单条数据
db.collection.findOneAndReplace()查询单条数据并替换
db.collection.findOneAndDelete()查询单条数据并删除
db.collection.findOneAndUpdate()查询单条数据并更新
db.collection.find()查询集合,无参数则查询所有,并返回一个游标对象
db.collection.findAndModify()查询并修改
db.collection.getIndexes()返回当前集合的所有索引数组
db.collection.group()提供简单的数据聚合功能
db.collection.isCapped()判断集合是否为定容量
db.collection.insert()在当前集合插入一条或多条数据(或叫文档)
db.collection.insertMany()在当前集合插入多条数据
db.collection.insertOne()在当前集合插入一条数据
db.collection.reIndex()重建当前集合的所有索引
db.collection.renameCollection()重命名集合名称
db.collection.replaceOne()替换集合中的一个文档(一条数据)
db.collection.remove()从当前集合删除数据
db.collection.save()已插入数据更新
db.collection.stats()返回当前集合的状态
db.collection.storageSize()返回当前集合已使用的空间大小
db.collection.totalSize()返回当前集合的总占用空间,包括所有文件和所有索引
db.collection.totalIndexSize()返回当前集合所有的索引所占用的空间大小
db.collection.updateMany()修改集合中的多条数据
db.collection.update()修改集合中的数据
db.collection.updateOne()修改集合中的一条数据
db.collection.validate()执行对集合验证操作

在mongodb中其实不需要专门创建集合,直接添加文档,mongodb也会自动生成集合的。
# name为必填参数,options为可选参数。capped若设置值为true,则size必须也一并设置
db.createCollection(
    name=<集合名称>, 
    options  = { 
        capped : <boolean>,     # 创建固定集合,固定集合指限制固定数据大小的集合,当数据达到最大值会自动覆盖最早的文档内容
        size : <bytes_size>,    # 指定固定集合存储的最大字节数,单位:字节数.
        max : <collection_size>   # 指定固定集合中包含文档的最大数量,单位:字节数
});

示例:

        # 添加文档到不存在的集合中,mongodb会自动创建集合
        db.集合.insert({"name":"python入门","price" : 31.4})  
        show collections # 或 show tables 或 db.getCollectionNames()
        db.集合.drop()    删除集合
        db.getCollection("集合")    查看集合
        db.集合                     查看集合
        db.printCollectionStats()    查看集合创建信息

数据类型

Type描述
ObjectID用于存储文档的ID,相当于主键,mongoDB中就是一个对象的返回值
String字符串是最常用的数据类型,MongoDB中的字符串必须是UTF-8编码。
Integer整数类型用于存储数值。整数可以是32位,也可以是64位,这取决于你的服务器。
Double双精度类型用于存储浮点值,mongodb中没有float浮点数这个说法
Boolean布尔类型用于存储布尔值(true/ false)
Arrays将数组、列表或多个值存储到一个键
Timestamp时间戳,用于记录文档何时被修改或创建。Date(),Timestamp(),ISODate()
Object用于嵌入文档, 相当于子属性是另一个json而已
Null空值,相当于 python的None
Symbol与字符串用法相同,常用于某些使用特殊符号的语言
Date用于以UNIX时间格式存储当前日期或时间。
Binary data二进制数据
Code用于将JavaScript代码存储到文档中
Regular expression正则表达式

添加文档
文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

# 添加文档
# 方式1:
db.集合.insert(<document>)  # document就是一个json
# 方式2:       
db.集合.insertOne(          # 如果文档存在_id主键为更新数据,否则就添加数据。
   <document>
)
# 方式3
# 一次性添加多个文档, 多次给同一个集合建议使用insertMany比insertOne效率更好
db.集合.insertMany(
   [ <document> , <document>, ... ]
)

操作:
use mofang;
// 添加一条数据
db.user_list.insert({"name":"laoli","age":33,"sex":true,"child":{"name":"xiaohuihui","age":3}});
// WriteResult({ "nInserted" : 1 })
// 添加一条数据
db.user_list.insertOne({"name":"xiaozhang","age":18,"sex":true});
// {
//     "acknowledged" : true,
//     "insertedId" : ObjectId("605021e6d5c7a55cc95c1cb7")
// }

// 添加多条数据
document1 = {"name":"xiaolan","age":16}
document2 = {"name":"xiaoguang","age":16}
db.user_list.insertMany([document1,document2]);

// {
//     "acknowledged" : true,
//     "insertedIds" : [
//         ObjectId("60502235d5c7a55cc95c1cba"),
//         ObjectId("60502235d5c7a55cc95c1cbb")
//     ]
// }

删除文档
db.集合.remove(
   <query>,  // removed的条件,一般写法:{"属性":{条件:值}},如果不填写条件,删除所有文档
   {
     justOne: <boolean>,      // 可选删除,是否只删除查询到的第一个文档,默认为false,删除所有
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)
操作:
// 删除满足条件的第一条数据
db.user_list.remove({"age":17},{"justOne":true})
// 删除满足条件的所有数据
db.user_list.remove({"name":"laowang"});
查询文档
// 直接显示查询的所有,find和findOne的第二个参数,也是一个json对象,
// 一般称之为字段投影,表示设置是否显示或隐藏指定数据字段。
// 获取一条
db.集合.findOne(
    <query>,     // 查询条件
    {
        <key>: 0, // 隐藏指定字段,例如:"_id":0,
        <key>: 1, // 显示指定字段,例如:"title":1,
        ....
    }
)
// 获取多条
db.集合.find(
    <query>,      // 查询条件
    {
        <key>: 0, // 隐藏指定字段,例如:"_id":0,
        <key>: 1, // 显示指定字段,例如:"title":1,
        ....
    }
)
# 以易读的方式来格式化显示读取到的数据,只能在find方法后面使用。
db.集合.find().pretty()

操作符

方法名描述
$mod取模计算
$regex
$text
$where
方法名描述
$and
$nor
$not
$or
方法名描述
$gt大于
$lte小于等于
$in包含
$nin不包含
$lt小于
$gte大于等于
$ne不等于
$eq等于
方法名描述
$all匹配所有
$size匹配数组元素个数
$elemMatch
方法名描述
$type数据类型操作符
$exists判断字段是否存在

字段 更新 操作符

方法名描述
$mul
$max
$min
$set设置某一个字段的值。
$inc对一个数字字段的某个field增加value
$rename字段的重命名
$unset删除字段。
$setOnInsert
$currentDate

数组 更新 操作符

方法名描述
$each
$sort
$position
$pull从数组field内删除一个等于value的值。
$push把value追加到field里。
$pushAll用法同$push一样,只是$pushAll一次可以追加多个值到一个数组字段内。
$addToSet加一个值到数组内,而且只有当这个值不在数组内才增加。
$pullAll用法同$pull一样,可以一次删除数组内的多个值。
$pop删除数组内的一个值。

聚合 管道 操作符

:group 查询操作符

方法名描述
$sum计算总和
$stdDevPop
$avg计算平均值
$min获取集合中所有文档对应值得最小值。
$first根据资源文档的排序获取第一个文档数据。
$stdDevSamp
$push在结果文档中插入值到一个数组中。
$max获取集合中所有文档对应值得最大值。
$addToSet在结果文档中插入值到一个数组中,但不创建副本。
$last根据资源文档的排序获取最后一个文档数据

:管道聚合阶段

方法名描述
$sort将输入文档排序后输出。
$limit用来限制MongoDB聚合管道返回的文档数。
$unwind将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$sample
$match用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$redact
$skip在聚合管道中跳过指定数量的文档,并返回余下的文档。
$group将集合中的文档分组,可用于统计结果。
$project

修改输入文档的结构。可以用来重命名、增加或删除域,

也可以用于创建计算结果以及嵌套文档。

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

数据库 方法

方法名描述
db.cloneDatabase()从指定主机上克隆数据库
db.currentOp()显示当前正在进行的操作
db.commandHelp()返回数据库命令的帮助信息
db.createCollection()创建一个聚集集合(table)
db.cloneCollection()在MongoDB实例之间复制集合数据
db.copyDatabase()从指定的机器上复制指定数据库数据到某个数据库
db.dropDatabase();删除当前使用数据库
db.fsyncLock()刷新写入磁盘并锁定该数据库,以防止写入操作,并协助备份操作
db.fsyncUnlock()允许继续进行写入锁住的数据库(解锁)
db.getLogComponents()返回日志消息详细级别
db.getLastErrorObj()查看完整的错误结果
db.getMongo()查看当前db的链接机器地址
db.getCollection()得到指定名称的聚集集合(table)
db.getName()查看当前使用的数据库
db.getPrevError()返回包含自上次错误复位所有的错误状态文件
db.getCollectionNames()得到当前db的所有聚集集合
db.getCollectionInfos()返回当前数据库中的所有集合信息
db.getLastError()返回上一次错误,如果没有错误则为空
db.hostInfo()返回当前数据库主机系统的相关信息
db.killOp()终止指定的操作
db.listCommands()显示公共数据库的命令列表
db.logout()注销登录
db.printCollectionStats()显示当前db所有聚集索引的状态
db.resetError()重置db.getPrevError()和getPrevError返回的错误信息
db.repairDatabase()修复当前数据库
db.repairDatabase()修复当前数据库
db.runCommand()运行一个数据库命令
db.serverStatus()返回当前数据库状态的概要
db.setProfilingLevel()修改当前数据库的分析级别
db.stats()显示当前db状态
db.shutdownServer()关闭当前数据库运行实例或安全停止有关操作进程
db.setLogLevel()设置一个单独的日志信息级别
db.version()查看当前db版本

show dbs                   显示所有数据库列表
show databases        显示所有数据库列表
use  <database>       切换数据库,如果数据库不存在则创建数据库。
db                        查看当前工作的数据库
db.getName()      查看当前工作的数据库
db.dropDatabase()    删除当前数据库,如果数据库不存在,也会返回{"ok":1}

db.stats()     查看当前数据库状态

数据库命令

游标 方法 (cursor Method)

方法名描述
cursor.snapshot()
cursor.itcount()
cursor.batchSize()
cursor.pretty()
cursor.hint()
cursor.min()
cursor.sort()
cursor.forEach()
cursor.limit()
cursor.returnKey()
cursor.comment()
cursor.next()
cursor.hasNext()
cursor.readConcern()
cursor.skip()
cursor.readPref()
cursor.tailable()
cursor.explain()
cursor.maxTimeMS()
cursor.max()
cursor.size()
cursor.close()
cursor.toArray()
cursor.showRecordId()
cursor.map()
cursor.count()
cursor.noCursorTimeout()
cursor.maxScan()
cursor.objsLeftInBatch()

副本集 方法

方法名描述
rs.initiate()
rs.addArb()
rs.help()
rs.printReplicationInfo()查看到副本集操作日志
rs.remove()减少副本集节点
rs.freeze()“冻结”mongodb实例
rs.status()查看副本集状态
db.printSlaveReplicationInfo查看复制集的同步状态
rs.add()增加副本集节点
rs.stepDown()将当前主库“降级”
rs.slaveOk()
rs.conf()
rs.syncFrom()
rs.reconfig()

用户 管理 

方法名描述
db.getUsers()获取 所有 用户
db.dropAllUsers()删除 所有 用户
db.updateUser()更新 用户
db.createUser()创建 用户
db.revokeRolesFromUser()
db.removeUser()删除 用户
db.grantRolesToUser()
db.getUser()获取 单个 用户
db.changeUserPassword()更改 用户 密码
db.auth()数据库认证、安全模式

创建一个数据库新用户用 db.createUser(user, writeConcern) 方法,如果用户存在则返回一个用户重复错误。

语法

{
    user: "<用户名>",
    pwd: "<密码>",
    customData: { <any information> }, # 任意内容,主要是为了表示用户身份的相关介绍 
    roles: [ # 角色和权限分配
        { role: "<role>", db: "<database>" },  # 也可以直接填写由mongoDB内置的角色,例如: "<role>"
        ...
    ]
}

mongo的用户是以数据库为单位来建立的,每个数据库有自己的管理员。
管理员可以管理自己的数据库,但是不能直接管理其他数据库,要先在admin数据库认证后才可以。管理员的权限设置包含了2块,分别是角色和权限,由roles属性进行设置。

内置角色

MongoDB 数据库默认角色 ( 所有角色:https://www.mongodb.com/docs/manual/reference/built-in-roles/#all-database-roles )

  • 数据库用户角色:read、readWrite; 
  • 数据库管理角色:dbAdmin、dbOwner、userAdmin;
  • 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager; 
  • 备份恢复角色:backup、restore; 
  • 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase 
  • 超级用户角色:root

# 有几个角色间接或直接提供了系统超级用户的访问权限(dbOwner 、userAdmin、userAdminAnyDatabase)

MongoDB 角色的区别如下:

  1. readAnyDatabase:允许用户读取任意数据库的数据,包括系统级数据库。
  2. readWriteAnyDatabase:
    允许用户对任意数据库进行读写操作,包括系统级数据库。
    此角色包含了 readAnyDatabase 的权限。
  3. userAdminAnyDatabase:
    允许用户在任意数据库中 "创建、修改和删除用户",以及授予或撤销其他用户的角色。
    此角色包含了 readAnyDatabase 的权限。
  4. dbAdminAnyDatabase:允许用户在任意数据库中执行管理库操作,例如:"创建、删除、重命名和修复数据库"等。
  5. root:包含所有 权限

常用命令:

show dbs     // 显示所有的数据库

use admin    // 切换到 admin 库

show users  // 查看当前库下的用户

db.createUser({user:'admin',pwd:'admin_passwd',roles:['root']})    // 创建超级用户
db.dropUser('test_user')    // 删除用户

db.auth('admin', 'admin_passwd')  // 密码认证
db.updateUser('admin', {pwd: 'admin@admin'})  //  修改用户密码
db.auth('admin','root')


db.getName()
use otherDB_name    # 切换 db
show collections    # 显示对应db的所有collection
db.getCollectionNames()

db.myself_db.insert({"name":"name 1",age:21})
db.myself_db.find()

use admin
db.shutdownServer()  # 关闭 MongoDB 实例

use my_test_db    // 跳转到需要添加用户的数据库
db.createUser({
    user: 'test_user',          // 用户名
    pwd: 'test_Test_123++--',      // 密码
    roles:[{
      role: 'readWrite',  // 读写权限角色
      db: 'my_test_db'     // 数据库名
    }]
})

然后在配置文件中添加如下配置信息

security:
  authorization: enabled

限制网络访问

  port: 38451 
  bindIp: 127.0.0.1

MongoDB 设置用户名密码和数据库连接

https://www.cnblogs.com/jiangqw/p/13344028.html
https://blog.csdn.net/hbtj_1216/article/details/120875957

给Admin数据库创建账户管理员

当前账号只能用于管理admin数据库账号,不能进行其他数据库的操作。

# 进入/切换数据库到admin中
use admin;
# 创建账户管理员
db.createUser({
    user: "oldboy",
    pwd: "123456",
    roles: [
        {role: "userAdminAnyDatabase",db:"admin"},
    ]
});

# 终端效果如下:
Successfully added user: {
    "user" : "oldboy",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}

创建超级管理员

当前账号可以进行数据库相关操作。

# 进入/切换数据库到admin中
use admin
# 创建超级管理员账号
db.createUser({
    user: "super",
    pwd: "123456",
    roles: [
        "root",  # 也可以这样写 {role:"root", db:"admin"}
    ]
})

db.createUser({
    user: "python",
    pwd: "123456",
    roles: [
        {role:"root", db:"admin"},
    ]
})

创建用户自己的数据库的角色

帐号是跟着数据库绑定的,所以是什么数据库的用户,就必须在指定库里授权和验证!!!

# 切换数据库,如果当前库不存在则自动创建
use mofang
# 创建管理员用户,为了保证不会报错,所以先删除同名管理员 db.system.users.remove({user:"mofang"});
db.createUser({
    user: "mofang",
    pwd: "123",
    roles: [
        { role: "dbOwner", db: "mofang"}
    ]
})

用户信息 ( 增、删、改、查 )

查看当前数据库下的管理用户。只需要切换到对应的库中即可查看

use mofang
show users

查看系统中所有的用户。需要切换到admin中使用账号管理员的权限进行操作

use admin
db.auth("root","123456")
db.system.users.find() # 只能在admin数据库中使用。

删除用户。db.system.users.remove(json条件)

# 有多种删除方式,下面是根据user用户名删除用户
db.system.users.remove({user:"mofang"});

# 删除效果:
WriteResult({ "nRemoved" : 1 })  # nRemoved 大于0表示成功删除管理员,等于0则表示没有删除。

修改密码

必须切换到对应的数据库下:db.changeUserPassword("账户名", "新密码")

use mofang
# 注册必须保证有这个管理员
db.changeUserPassword("mofang", "123456")

开启 mongodb 账户认证机制

sudo vim /etc/mongod.conf
# 找到31行附近的 security,去掉左边注释符号(#)
security:
    authorization: enabled

:wq
# 重启mongdb,配置生效
sudo systemctl restart mongod

# 开启了账户认证机制以后,再次进入mofang
mongo
use mofang
show users    # 此处会报错如:uncaught exception: Error: command usersInfo requires authentication
db.auth("mofang","123")   # 此处认证时填写错误密码,报错如下:
# Error: Authentication failed.
# 0
db.auth("mofang","123456")  # 此处认证时填写正确密码,效果如下:
# 1
show users    # 此时经过认证以后,当前命令就不会被限制了。 

注意:

如果上面重启以后,认证机制不生效,则执行如下代码:

sudo pkill mongod                              # 杀死mongod服务
sudo mongod -f /etc/mongod.conf --fork --auth  # --auth 表示以认证模式启动服务,不加则关闭

查询器

比较运算

操作格式语法例子SQL中的类似语句
等于{<key>:<val>}
{<key>:{$eq:<val>}}
db.集合.find({"name":"xiaoming"})where name = 'xiaoming'
小于{<key>:{$lt:<val>}}db.集合.find({"age":{$lt:17}})where age < 17
小于或等于{<key>:{$lte:<val>}}db.集合.find({"age":{$lte:17}})where age <= 17
大于{<key>:{$gt:<val>}}db.集合.find({"age":{$gt:17}})where age > 17
大于或等于{<key>:{$gte:<val>}}db.集合.find({"age":{$gte:17}})where age >= 17
不等于{<key>:{$ne:<val>}}db.集合.find({"age":{$ne:17}})where age != 17
包含{<key>:{$in:<val>}}db.集合.find({"age":{$in:[1,2,3]}})where age in (1,2,3)

db.user_list.find({"age":{$lte:18}})
db.user_list.find({"age":{$gte:18}})
db.user_list.find({"age":{$in:[16,33]}})
db.user_list.find({"child.age":{$in:[3]}})

逻辑运算

操作语法语法例子
$and{<key>:<val>,<key>:<val>,...}db.集合.find({key1:value1, key2:value2})
$or{$or: [{<key>: <val>}, {<key>:<val>}]}db.集合.find({$or: [{key1: value1}, {key2:value2}]})
$and$or{<key>:<val>, $or: [{<key>: <val>}, {<key>:<val>}]}
{$and:[{$or:[{<key>:<val>},..]},$or:[{<key>:<val>},..]}]}
db.集合.find({key1:value1, $or: [{key1: value1}, {key2:value2}]})
$not{<key>:{$not:{<$运算符>:<val>}}}$not操作符不支持``$regex`正则表达式操作

// 查询age=18 并且 sex=true
db.user_list.find({
    $and:[
        {"age":{$eq:18}},
        {"sex":{$eq:true}}
    ]
})
// 简写:
db.user_list.find({
    $and:[
        {"age":18},
        {"sex":true}
    ]
})
// 继续简写;
db.user_list.find({ "age":18, "sex":true})

// 查询age=16或者age=18
db.user_list.find({
    $or:[
        {"age":{$eq:16}},
        {"age":{$eq:18}}
    ]
})

// 查询年龄!=16的
db.user_list.find({"age":{$not:{$eq:16}}})
db.user_list.find({"age":{$ne:16}})


// 查询age=33的男生 或者 age=18的男生

其他运算符

操作格式语法例子说明
$type{<key>:{$type: <datetype>}}db.集合.find({"name":{$type:'string'}})匹配指定键是指定数据类型的文档
number 数值型
string 字符串
bool 布尔类型
object json文档对象类型
array 数组类型
$exists{<key>:{$exists:<bool>}db.集合.find({"title":{$exists:true}})匹配具有指定键的文档,存在指定字段的文档
$regex{ <key>:/模式/<修正符>}
{<key>:{$regex:/模式/<修正符>}}
db.集合.find({"name":{$regex:/张$/}})按正则匹配
$mod{<key>: {$mod: [除数, 余数]}}db.集合.find({"age":{$mod:[10,0]}})算数运算,取模,语法中举例是age除以10==0

自定义条件函数

// 用法1,逻辑比较复杂的情况,可以使用更多的javascript进行运算处理:
db.集合.find({$where: function(){
    return <this.字段> <运算符> <条件值>;
}}});

// 用法2,相对没那么复杂的:
db.集合.find({$where:"<this.字段> <运算符> <条件值>"});
// db.集合.find({$where:"name = 'xiaoming'"});

/*
{ "_id" : ObjectId("6048de865a4f41cf6903b041"), "onumber" : "0000000000001819", "date" : "2020-09-01", "title" : "购买商品-1819", "user_id" : 10, "items" : [ { "goods_id" : 10, "goods_attr" : 1819, "price" : 100 }, { "goods_id" : 11, "goods_attr" : 1820, "price" : 80 } ] }

只要goods_attr > 1700 and goods_attr < 1800
*/

db.orders.find({$where: function(){
    for( goods of this.items){
        if(goods.goods_attr > 1700 && goods.goods_attr < 1800){
            return true;
        }else{
            return false;
        }
    }
}});

排序显示

db.集合.find().sort({<key>:1})  // 升序,默认为升序
db.集合.find().sort({<key>:-1}) // 倒序, 

字段投影

find()方法默认将返回文档的所有数据,但是可以通过设置find()的第二个参数projection,设置值查询部分数据。

// 获取一条
db.集合.findOne(
    <query>,     // 查询条件
    {
        <key>: 0, // 隐藏指定字段,例如:"_id":0,
        <key>: 1, // 显示指定字段,例如:"title":1,
        ....
    }
)
// 获取多条
db.集合.find(
    <query>,      // 查询条件
    {
        <key>: 0, // 隐藏指定字段,例如:"_id":0,
        <key>: 1, // 显示指定字段,例如:"title":1,
        ....
    }
)

> db.user_list.find({"mobile":{$regex:/^133\d{8}$/}},{"_id":0}).sort({"mobile":-1})
    { "name" : "xiaoming", "mobile" : "13333355678" }
    { "name" : "xiaoming", "mobile" : "13333345678" }
    { "name" : "xiaoming", "mobile" : "13312345678" }

> db.user_list.find({"mobile":{$regex:/^133\d{8}$/}},{"_id":0,"name":0}).sort({"mobile":-1})
    { "mobile" : "13333355678" }
    { "mobile" : "13333345678" }
    { "mobile" : "13312345678" }

> db.user_list.find({"mobile":{$regex:/^133\d{8}$/}},{"name":1}).sort({"mobile":-1})
    { "_id" : ObjectId("60502fb7d5c7a55cc95c1cc4"), "name" : "xiaoming" }
    { "_id" : ObjectId("60502fb4d5c7a55cc95c1cc3"), "name" : "xiaoming" }
    { "_id" : ObjectId("60502fb1d5c7a55cc95c1cc2"), "name" : "xiaoming" }

> db.user_list.find({"mobile":{$regex:/^133\d{8}$/}},{"name":1,"_id":0}).sort({"mobile":-1})
    { "name" : "xiaoming" }
    { "name" : "xiaoming" }
    { "name" : "xiaoming" }

限制与偏移

limit方法用于限制返回结果的数量

skip方法用于设置返回结果的开始位置

db.集合.find(...).limit(结果数量).skip(跳过数量)

更新文档

// 更新一条
db.集合.update(
   <query>,   // update的查询条件,一般写法:{"属性":{条件:值}}
   <update>,  // update的更新数据,一般写法 { $set:{"属性":"值"} } 或者 { $inc:{"属性":"值"} }
   {
     upsert: <boolean>, // 可选参数,如果文档不存在,是否插入objNew, true为插入,默认是false,不插入
     multi: <boolean>,  // 可选参数,是否把满足条件的所有数据全部更新,设置更新1条还是多条
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)

// 更新多条
db.集合.updateMany(
   <query>,   // update的查询条件,一般写法:{"属性":{条件:值}}
   <update>,  // update的对象,一般写法 { $set:{"属性":"值"} } 或者 { $inc:{"属性":"值"} }
   {
     upsert: <boolean>, // 可选参数,如果文档不存在,是否插入objNew, true为插入,默认是false,不插入
     multi: <boolean>,  // 可选参数,是否把满足条件的所有数据全部更新
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)

update 更新运算符 [修改器]

操作语法
$incdb.集合.update({<key1>:<val1>},{$inc:{<key2>:<val2>}})更新key1=val1的文档中key2的值为val2,类似python的递增递减
递减,则{ $inc:{<key2>:-<val2>} }
$setdb.集合.update({<key1>:<val>}, {$set:{<key2>:<val2>}})更新key1=val1的文档中key2的值为val2,如果key2不存在则新增对应键值对
$unsetdb.集合.update({<key1>:<val>}, {$unset:{<key2>:<val2>}})移除key1=val1的文档中key2=val2这个键值对
$pushdb.集合.update({<key1>:<val>}, {$push:{<key2>:<val2>}})给key1=val1的文档中key2列表增加1个数组成员val2。
key2必须是数组,增加多个成员,用$pushAll
$pulldb.集合.update({<key1>:<val>}, {$pull:{<key2>:<val2>}})与push相反,给key1=val1的文档中key2列表删除1个指定成员val2,删除多个成员,使用$pullAll
$popdb.集合.update({<key1>:<val>}, {$pop:{<key2>:<val2>}})给key1=val1的文档中key2列表移除第一个或最后一个成员。
val2只能是1(最后面)或-1(最前面),与python相反

索引操作

前面学习过MySQL,我们知道数据库里给数据构建索引通常能够极大的提高数据查询的效率,缩短查询耗时,如果没有索引,数据库在查询数据时必然会扫描数据表中的每个记录并提取那些符合查询条件的记录。同理,在MongoDB中构建索引也可以提高数据的查询效率和缩短查询耗时,没有索引的情况也是一样,MongoDB也会再查询数据时扫描集合中的每个文档并提取符合查询条件的文档。这种扫描全集合的查询效率是无疑是非常低下的,特别在处理大量的集合数据时,查询时间可能会达到几十秒甚至几分钟,这对用户体验来说是非常致命的。

文档:https://docs.mongodb.com/manual/indexes/#default-id-index

准备数据

for(var i=0; i<1000000; i++){  
    db.orders.insert({
        "onumber": ( "0000000000000000" + i ).substr( String(i).length ),  
        "date": "2020-09-01",  
        "title": "购买商品-"+i,
        "user_id": parseInt(i/200)+1,
        "items" :[{ 
            "goods_id" : parseInt(i/200)+1,
            "goods_attr" : i,  
            "price" : 100.0
        },{ 
            "goods_id" : parseInt(i/200)+2,
            "goods_attr" : i+1,  
            "price" : 80.0
        }]
    })
    if(i%10000==0){
        print("已经添加了"+parseInt(i/10000)+"万条数据!");
    }
}

注意事项

  1. MongoDB的索引是存储在运行内存(RAM)中的,所以必须确保索引的大小不超过内存的限制。

    如果索引的大小超过了运行内存的限制,MongoDB会删除一些索引,这将导致性能下降。

  2. MongoDB的索引在部分查询条件下是不会生效的。

    • 正则表达式及非操作符,如 $nin,$not , 等。
    • 算术运算符,如 $mod, 等。
    • $where自定义查询函数。
  3. 索引会在写入数据(添加、更新和删除)时重排,如果项目如果是写多读少,则建议少使用或者不要使用索引。

  4. 一个集合中索引数量不能超过64个。

  5. 索引名的长度不能超过128个字符。

  6. 一个复合索引最多可以有31个字段。

  7. mongodb索引统一在system.indexes集合中管理。这个集合只能通过createIndexdropIndexes来操作。

查看索引

// 获取当前集合中已经创建的所有索引信息
db.集合.getIndexes()
/*
[{ 
    "v" : 2,   // 索引版本
    "key" : {  // 索引的字段及排序方向(1表示升序,-1表示降序)
        "_id" : 1   // 根据_id字段升序索引
    }, 
    "name" : "_id"   // 索引的名称
}]
*/
// 获取当前集合中已经创建的索引总大小,以字节为单位返回结果
db.集合.totalIndexSize()
// 获取当前数据库中所有的索引【不会显示_id主键】
db.system.indexes.find()

MongoDB默认会为插入的文档生成_id字段(如果应用本身没有指定该字段),_id是文档唯一的标识,为了保证能根据文档id快递查询文档,MongoDB默认会为集合创建_id字段的主键索引。

查询分析

与SQL语句类似,MongoDB也提供了一个explain,供开发者进行查询分析。

explain的使用有3个参数,分别是:queryPlanner、executionStats、allPlansExecution,默认是queryPlanner,开发中常用的是executionStats。

db.orders.find({"title":"购买商品-19"}).explain("executionStats")
/*
{
    "queryPlanner" : {  # 被查询优化器选择出来的查询计划
        "plannerVersion" : 1,  # 查询计划版本
        "namespace" : "test.orders", # 要查询的集合
        "indexFilterSet" : false,  # 是否了使用索引
        "parsedQuery" : {  # 查询条件
            "title" : {
                "$eq" : "购买商品-19"
            }
        },
        "winningPlan" : {     # 最佳执行计划
            "stage" : "COLLSCAN", # 扫描类型/扫描阶段
            "filter" : {     # 过滤条件
                "title" : {
                    "$eq" : "购买商品-19"
                }
            },
            "direction" : "forward"  # 查询方向,forward为升序,backward表示倒序。
        },
        "rejectedPlans" : [ ]   # 拒绝的执行计划
    },
    "executionStats" : {  # 最佳执行计划的一些统计信息
        "executionSuccess" : true,  # 是否执行成功
        "nReturned" : 1,   # 返回的结果数
        "executionTimeMillis" : 346,  # 执行耗时
        "totalKeysExamined" : 0,      # 索引扫描次数
        "totalDocsExamined" : 1000000,  # 文档扫描次数,所谓的优化无非是让totalDocsExamined和nReturned的值接近。
        "executionStages" : {     # 执行状态
            "stage" : "COLLSCAN",  # 扫描方式/扫描阶段
            "filter" : {
                "title" : {
                    "$eq" : "购买商品-19"
                }
            },
            "nReturned" : 1,   # 返回的结果数
            "executionTimeMillisEstimate" : 5,   # 预估耗时
            "works" : 1000002,   # 工作单元数
            "advanced" : 1,      # 优先返回的结果数
            "needTime" : 1000000,
            "needYield" : 0,
            "saveState" : 1000,
            "restoreState" : 1000,
            "isEOF" : 1,
            "direction" : "forward",
            "docsExamined" : 1000000   # 文档检查数目,与totalDocsExamined一致
        }
    },
    "serverInfo" : {   # 服务器信息
        "host" : "ubuntu",
        "port" : 27017,
        "version" : "4.4.2",
        "gitVersion" : "15e73dc5738d2278b688f8929aee605fe4279b0e"
    },
    "ok" : 1
}

*/

stage的扫描类型:

类型名称描述期望
COLLSCAN全表扫描False
IXSCAN索引扫描True
FETCH根据索引去检索指定documentTrue
IDHACK针对_id进行查询True
COUNTSCANcount不使用Index进行count时返回False
COUNT_SCANcount使用了Index进行count时返回True
SUBPLA未使用到索引的$or查询时返回False
TEXT使用全文索引进行查询时返回-
SORT使用sort排序但是无index时返回False
SKIP使用skip跳过但是无index时返回False
PROJECTION使用limit限定结果但是无index时返回False

创建索引

MongoDB支持多种类型的索引,包括普通索引、复合索引、多列索引、全文索引、哈希索引地理位置索引等,每种类型的索引有不同的使用场合。ttl索引本质上就是普通索引。另外,MongoDB的全文索引很弱智,如果真要用在开发中,还是建议使用elasticsearch或者Sphinx。

// 创建索引
db.集合.createIndex({
    // 单个字段,则为普通索引,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
    "字段名1": <sort|type>,       // type的值可以是text,表示创建全文索引。db.集合.find({$text:{$search:"字符串"}})
    "字段名2": <sort|type>,       // 多个字段,则为复合索引
    "字段名3": [<值1>,<值2>,...],  // 多列索引
    ....
}, {
    background: <Boolean>,   // 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,默认为false
    unique: <Boolean>,  // 是否建立唯一索引,默认值为false,也叫唯一索引
    name: <String>,   // 索引的名称,不填写,则MongoDB会通过连接索引的字段名和排序顺序生成一个索引名称 
    expireAfterSeconds: <integer>, // 设置索引的过期时间,类似redis的expire,也叫TTL索引
    sparse: <Boolean>,  // 对文档中不存在的字段数据是否不启用索引,默认为False
});


// 单字段索引[普通索引]
 db.集合.createIndex({
    "字段名1": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
 }, {
    ....
 })
// 普通索引创建: db.orders.createIndex({"title":1})
// 查询基本使用: db.orders.find({"title":"购买商品-19"})


// 多字段索引,也叫复合索引。[类似mysql里面的联合索引]
 db.集合.createIndex({
    "字段名1": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
    "字段名2": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
 }, {
    ....
 })
// 复合索引的使用对单条件的查找是没有帮助的,必须多字段[必须包含复合索引的字段]条件使用
// 复合索引创建:db.orders.createIndex({"date":1,"title":1});
// 查询基本使用:
//     db.orders.find({"date":"2020-09-01","title":"购买商品-1007"});
//     db.orders.find({"date":"2020-09-01","onumber":"0000000000001007","title":"购买商品-1007","onumber":});


// 全文索引
 db.集合.createIndex({
    "字段名1": <type>,    // type的值只能是text,表示创建全文索引。db.集合.find({$text:{$search:"字符串"}})
 }, {
    ....
 })

// 全文索引创建: db.orders.createIndex({"title":"text"})
// 查询基本使用: db.orders.find({$text:{$search:"商品-19"}}).explain("executionStats")

// 多列索引[应用的地方是在列表属性]
 db.集合.createIndex({
    "字段名3": [<值1>,<值2>,...],
 }, {
    ....
 });

// 创建测试数据
db.doc.drop()
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题2","tags":["java","mvp"]})
db.doc.insert({"title":"标题3","tags":["java","mvp"]})
db.doc.insert({"title":"标题2","tags":["java","mvp"]})
db.doc.insert({"title":"标题3","tags":["python"]})
db.doc.insert({"title":"标题4","tags":["python"]})
db.doc.insert({"title":"标题2","tags":["python","flask"]})
db.doc.insert({"title":"标题3","tags":["java"]})
// 创建多列索引: db.doc.createIndex({"tags":1})
// 查询数据: db.doc.find({"tags":["python"]}).explain("executionStats")

// 唯一索引
db.集合.createIndex({
    "字段名1": <sort>,
}, {
    unique: true,     // 是否建立唯一索引,默认值为false,也叫唯一索引
})
// 创建唯一索引: db.orders.createIndex({"onumber":1},{unique:true});
// 查询数据: db.orders.find({"onumber":"0000000000001019"}).explain("executionStats")

// ttl索引
// 使用ttl索引,索引关键字段必须是 Date 类型,如果该字段不是date类型或者文档中不存在该字段,则文档不会进行过期处理
// 数据过期的删除工作是在独立线程内执行的,默认平均60s扫描一次。

// 例如:在文档创建1小时后,删除文档
db.集合.createIndex({"date": 1},{expireAfterSeconds: 3600})

// 在文档创建后,由索引字段值指定的时间删除文档
db.集合.createIndex({"date": 1},{expireAfterSeconds: 0}) // 文档中date字段对应的时间就变成了过期时间了.
db.集合.insert( {
   "date": new Date('2020-02-06 10:00:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
})

// 创建索引:db.tasks.createIndex({"expire_time":1},{expireAfterSeconds:0})
// 创建测试数据
db.tasks.insert( {
   "expire_time": new Date('2021-06-17 22:24:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});
db.tasks.insert( {
   "expire_time": new Date('2021-06-17 18:25:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});
db.tasks.insert( {
   "expire_time": new Date('2021-06-17 18:27:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});

// 重建索引[一般是在长期项目运行下来,索引创建时间太久了,性能下降的时候使用。不能在高峰期时运行]
db.集合.reIndex();

删除索引

MongoDB给文档主键_id默认创建单字段索引是无法删除的。

// 删除单个索引
db.集合.dropIndex("索引名称")

// 删除所有索引
db.集合.dropIndexes()

PyMongo

安装:pip install pymongo

数据库连接,无密码

import pymongo
mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")

数据库连接,有密码

# 方式1:
import pymongo
from urllib import parse
username = parse.quote_plus('mofang')   # 对用户名进行编码
password = parse.quote_plus('123456')  # 对密码进行编码
database = "mofang" # 数据库名称
host     = "127.0.0.1"
port     = "27017"
mongo = pymongo.MongoClient('mongodb://%s:%s@%s:%s/%s' % ( username, password, host, port, database))

"""
# 方式2:
import pymongo
from urllib import parse
username = parse.quote_plus('mofang')   # 对用户名进行编码
password = parse.quote_plus('123456')  # 对密码进行编码
database = "mofang" # 数据库名称
mongo = pymongo.MongoClient('mongodb://127.0.0.1:27017') # 组装成url进行连接
my_db = mongo["mofang"]
my_db.authenticate(username,password)
"""

"""
# 方式3:
import pymongo
from urllib import parse
username = parse.quote_plus('root')   # 对用户名进行编码
password = parse.quote_plus('123456')  # 对密码进行编码
host     = "127.0.0.1"
port     = "27017"
database = "mofang" # 数据库名称
mongo = pymongo.MongoClient('mongodb://%s:%s@%s:%s/admin' % ( username, password, host, port))
my_db = mongo[database]
my_collection = my_db["my_collection"] # 没有往集合里面保存文档之前,mongdb不会真正创建集合!
"""

数据库管理

import pymongo

# 数据库连接
mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")

# 创建数据库
my_db  = mongo["my_db"] # 没有往集合里面保存文档之前,mongdb不会真正创建集合!

# 查看数据库列表
print(mongo.list_database_names()) # 上面的 my_db 因为没有内容,所以没有被创建的。

集合管理

import pymongo

mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
my_db = mongo["my_db"]

my_collection = my_db["my_collection"] # 没有往集合里面保存文档之前,mongdb不会真正创建集合!

# 查看集合列表
print(my_db.list_collection_names())

# 删除集合
my_collection.drop() # 删除成功返回true,如果集合不存在,返回false

文档管理

添加文档

import pymongo
mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
my_db = mongo["my_db"]
my_collection = my_db["my_collection"]

# 添加一个文档
document = { "name": "xiaoming", "mobile": "13012345678","age":16}
ret = my_collection.insert_one(document)
print(ret.inserted_id) # 返回InsertOneResult对象
# 插入文档时,如果没有指定_id,将自动分配一个唯一的id。

# 添加多个文档
document_list = [
  { "name": "xiaoming", "mobile": "13033345678","age":17},
  { "name": "xiaohong", "mobile": "13044345678","age":18},
  { "name": "xiaohei",  "mobile": "13612345678","age":18},
]
ret = my_collection.insert_many(document_list)

# 打印文档_id值列表:
print(ret.inserted_ids)

删除文档

import pymongo

mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
my_db = mongo["my_db"]
my_collection = my_db["my_collection"]

# 删除一个文档
query = {"name":"xiaoming"}
my_collection.delete_one(query)

# 删除多个文档
query = { "mobile": {"$regex": "^130"} }
ret = my_collection.delete_many(query)
print("删除了%d个文档" % ret.deleted_count)

更新文档

import pymongo

mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
my_db = mongo["my_db"]
my_collection = my_db["my_collection"]

# 更新一个文档
query = { "name": "xiaoming" }
data = { "$set": { "age": 18 } }
my_collection.update_one(query, data)

# 更新所有文档
query = { "mobile": {"$regex": "^130"} }
data = { "$set": { "age": 18 } }
my_collection.update_many(query, data)

查询文档

import pymongo

mongo = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
my_db = mongo["my_db"]
my_collection = my_db["my_collection"]

# 查看一个文档
ret = my_collection.find_one()
print(ret)

# 查看所有文档
for document in my_collection.find():
    print(document)

# 查看文档部分字段,find和find_one的第二个参数表示控制字段的显示隐藏,1为显示,0为隐藏
for document in my_collection.find({},{ "_id": 0, "name": 1, "mobile": 1 }):
    print(document)

# 条件查询
query = { "age": 18 }
document_list = my_collection.find(query)
for document in document_list:
    print(document)

# 比较运算符
query = { "age": {"$gt":17} }
document_list = my_collection.find(query)
for document in document_list:
    print(document)

# 排序显示
# 单个字段排序:
#         sort("键", 1) 升序
#         sort("键",-1) 降序

# 多个字段排序:
#       sort([("键1",1),("键2",-1)])
document_list = my_collection.find().sort("age")
for document in document_list:
    print(document)
    
# 限制查询结果数量
document_list = my_collection.find().limit(3)
print(document_list)

# 偏移、跳过
#    skip(int)
document_list = my_collection.find().limit(3).skip(3) # 从第3篇文档开始获取3篇文档
print(document_list)

# 自定义条件函数
document_list = my_collection.find({"$where":"this.age==18"})
print(document_list)

三、学习 MongoDB

推荐学习 MongoDB 书籍。动物书《MongoDB权威指南-第二版》,非常经典
学习 MongoDB 的官方手册:https://docs.mongodb.com/manual/crud/
学习 MongoDB 的入门教程:http://www.tutorialspoint.com/mongodb/mongodb_create_database.htm

参考文档:

菜鸟教程:http://www.runoob.com/mongodb/mongodb-databases-documents-collections.html

不管我们学习什么数据库都应该学习其中的基础概念,在mongodb 中基本的概念是文档、集合、数据库,下面我们挨个介绍。

下表将帮助您更容易理解Mongo中的一些概念:

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

通过下图实例,我们也可以更直观的了解Mongo中的一些概念:

数据库

一个mongodb中可以建立多个数据库。

MongoDB的默认数据库为"db",该数据库存储在data目录中。

MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。

"show dbs" 命令可以显示所有数据的列表。

执行 "db" 命令可以显示当前数据库对象或集合。

$ ./mongo
MongoDB shell version: 3.0.6
connecting to: test
> db
test
> ./mongo
MongoDB shell version: 3.0.6
connecting to: test
> db
test
> 

运行"use"命令,可以连接到一个指定的数据库。

> use local
switched to db local
> db
local
>  use local
switched to db local
> db
local
> 

以上实例命令中,"local" 是你要链接的数据库。

在下一个章节我们将详细讲解MongoDB中命令的使用。

数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串。

  • 不能是空字符串("")。
  • 不得含有' '(空格)、.、$、/、\和\0 (空字符)。
  • 应全部小写。
  • 最多64字节。

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

文档

文档是一组键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

一个简单的文档例子如下:

{"site":"www.runoob.com", "name":"菜鸟教程"}"site":"www.runoob.com", "name":"菜鸟教程"}

下表列出了 RDBMS 与 MongoDB 对应的术语:

RDBMSMongoDB
数据库数据库
表格集合
文档
字段
表联合嵌入文档
主键主键 (MongoDB 提供了 key 为 _id )
数据库服务和客户端
Mysqld/Oraclemongod
mysql/sqlplusmongo

需要注意的是:

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:

  • 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
  • .和$有特别的意义,只有在特定环境下才能使用。
  • 以下划线"_"开头的键是保留的(不是严格要求的)。

集合

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。

集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

比如,我们可以将以下不同数据结构的文档插入到集合中:

{"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google"}
{"site":"www.runoob.com","name":"菜鸟教程","num":5}"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google"}
{"site":"www.runoob.com","name":"菜鸟教程","num":5}

当第一个文档插入时,集合就会被创建。

合法的集合名

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。 

如下实例:

db.col.findOne().col.findOne()

capped collections

Capped collections 就是固定大小的collection。

它有很高的性能以及队列过期的特性(过期按照插入的顺序). 有点和 "RRD" 概念类似。

Capped collections是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能 和标准的collection不同,你必须要显式的创建一个capped collection, 指定一个collection的大小,单位是字节。collection的数据存储空间值提前分配的。

要注意的是指定的存储大小包含了数据库的头信息。

db.createCollection("mycoll", {capped:true, size:100000}).createCollection("mycoll", {capped:true, size:100000})
  • 在capped collection中,你能添加新的对象。
  • 能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。
  • 数据库不允许进行删除。使用drop()方法删除collection所有的行。
  • 注意: 删除之后,你必须显式的重新创建这个collection。
  • 在32bit机器中,capped collection最大存储为1e9( 1X109)个字节。

元数据

数据库的信息是存储在集合中。它们使用了系统的命名空间:

dbname.system.*.system.*

在MongoDB数据库中名字空间 .system.* 是包含多种系统信息的特殊集合(Collection),如下:

集合命名空间描述
dbname.system.namespaces列出所有名字空间。
dbname.system.indexes列出所有索引。
dbname.system.profile包含数据库概要(profile)信息。
dbname.system.users列出所有可访问数据库的用户。
dbname.local.sources包含复制对端(slave)的服务器信息和状态。

对于修改系统集合中的对象有如下限制。

在{{system.indexes}}插入数据,可以创建索引。但除此之外该表信息是不可变的(特殊的drop index命令将自动更新相关信息)。

{{system.users}}是可修改的。 {{system.profile}}是可删除的。


MongoDB 数据类型

下表为MongoDB中常用的几种数据类型。

数据类型描述
String字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean布尔值。用于存储布尔值(真/假)。
Double双精度浮点值。用于存储浮点值。
Min/Max keys将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array用于将数组或列表或多个值存储为一个键。
Timestamp时间戳。记录文档修改或添加的具体时间。
Object用于内嵌文档。
Null用于创建空值。
Symbol符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID对象 ID。用于创建文档的 ID。
Binary Data二进制数据。用于存储二进制数据。
Code代码类型。用于在文档中存储 JavaScript 代码。
Regular expression正则表达式类型。用于存储正则表达式。

下面说明下几种重要的数据类型。

ObjectId

ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:

  • 前 4 个字节表示创建 unix时间戳,格林尼治时间 UTC 时间,比北京时间早了 8 个小时
  • 接下来的 3 个字节是机器标识码
  • 紧接的两个字节由进程 id 组成 PID
  • 最后三个字节是随机数

MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象

由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:

> var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2017-11-25T07:21:10Z") var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2017-11-25T07:21:10Z")

ObjectId 转为字符串

> newObject.str
5a1919e63df83ce79df8b38f newObject.str
5a1919e63df83ce79df8b38f

字符串

BSON 字符串都是 UTF-8 编码。

时间戳

BSON 有一个特殊的时间戳类型用于 MongoDB 内部使用,与普通的 日期 类型不相关。 时间戳值是一个 64 位的值。其中:

  • 前32位是一个 time_t 值(与Unix新纪元相差的秒数)
  • 后32位是在某秒中操作的一个递增的序数

在单个 mongod 实例中,时间戳值通常是唯一的。

在复制集中, oplog 有一个 ts 字段。这个字段中的值使用BSON时间戳表示了操作时间。

BSON 时间戳类型主要用于 MongoDB 内部使用。在大多数情况下的应用开发中,你可以使用 BSON 日期类型。

日期

表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。

> var mydate1 = new Date()     //格林尼治时间
> mydate1
ISODate("2018-03-04T14:58:51.233Z")
> typeof mydate1
object var mydate1 = new Date()     //格林尼治时间
> mydate1
ISODate("2018-03-04T14:58:51.233Z")
> typeof mydate1
object
> var mydate2 = ISODate() //格林尼治时间
> mydate2
ISODate("2018-03-04T15:00:45.479Z")
> typeof mydate2
object var mydate2 = ISODate() //格林尼治时间
> mydate2
ISODate("2018-03-04T15:00:45.479Z")
> typeof mydate2
object

这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。

返回一个时间类型的字符串:

> var mydate1str = mydate1.toString()
> mydate1str
Sun Mar 04 2018 14:58:51 GMT+0000 (UTC) 
> typeof mydate1str
string var mydate1str = mydate1.toString()
> mydate1str
Sun Mar 04 2018 14:58:51 GMT+0000 (UTC) 
> typeof mydate1str
string

或者

> Date()
Sun Mar 04 2018 15:02:59 GMT+0000 (UTC)    Date()
Sun Mar 04 2018 15:02:59 GMT+0000 (UTC)   

4、mongosh、Robo3T、与 SQL 语法比较

From:http://www.cnblogs.com/dacongge/p/7344311.html
MongoDB基本管理命令:https://blog.csdn.net/shirdrn/article/details/7105539
MongoDB常用操作命令大全:https://blog.csdn.net/piaocoder/article/details/52384756
mongodb 命令行基本命令使用大全:https://blog.csdn.net/qq_27093465/article/details/54601598
MongoDB日常运维操作命令小结:https://www.cnblogs.com/kevingrace/p/8184087.html
mongodb命令行(增删改查、高级查询):https://blog.csdn.net/wangpengzhi19891223/article/details/51549077
菜鸟教程 之 MongoDB 教程:http://www.runoob.com/mongodb/mongodb-tutorial.html
MongoDB 中文手册:http://www.mongodb.org.cn/manual/

安装 mongodb shell
下载安装包:https://www.mongodb.com/try/download/shell
下载成功后解压,为了方便,这里直接解压到 mongodb/bin/MongoShell目录
将 bin 目录添加到 Path 中 

Shell 的一些操作

命名规范

  • 不能是空字符串("")。
  • 不得含有 ' '(空格)、.、$、/、\和\0 (空字符)。
  • 应全部小写。
  • 最多64字节。
  • 一些系统关键字。

1、创建一个数据库

执行下面命令。example:数据库名(如果只创建数据库,而不做处理,这个空数据库会被删除。)命令:use example

2、查看所有数据库 

验证上面的创建的数据,下面不存在。命令:show dbs

3、给指定数据库添加集合并添加记录

user:集合名    insert:插入一条记录

> db.user.insert({name:'yujie'})
> WriteResult({ "nInserted" : 1 }) --表示成功

再 show dbs 查看,数据库创建成功。

添加 字段

data = dict(
    field_1=value_1,
    field_2=value_2,
    field_3=value1_3,
)
db_tb.update_one({"_id": ObjectId("5b345e03651a790cd872b633")}, {"$set": data})

更新字

db.products.update(
    {_id: 100},
    { $set:{
            quantity: 500,
            details: {model: "14Q3", make: "xyz"},
            tags: ["coats", "outerwear", "clothing"]
        }   
    }
)

python 示例:

user_name = 'king'
db_tb.update_one({"_id": ObjectId("5b345e03651a7")}, {"$set": {'name': user_name}})

4、查看所有文档

命令:show collections

5、查看 user文档 中的所有记录

> db.user.find()
{ "_id" : ObjectId("598c05e503bd136ff3ea0257"), "name" : "xiaoming" }

查看记录数量:> db.user.find().count()

6、查看 user文档 中的第一条记录

> db.user.findOne()
{ "_id" : ObjectId("598c05e503bd136ff3ea0257"), "name" : "xiaoming" }

7、更新文档数据 

Mongodb 数据更新命令(update、save):https://www.cnblogs.com/yu-zhang/p/5210966.html

update({查询条件}, {更新内容})

> db.user.update({name:'xiaoming'},{$set:{name:'小明'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.user.find()
{ "_id" : ObjectId("598c05e503bd136ff3ea0257"), "name" : "小明" }

6、删除文档数据 

remove({条件})

> db.user.insert({name:'zhangsan'}) --先插入一条
WriteResult({ "nInserted" : 1 })

> db.user.find() --再查询
{ "_id" : ObjectId("598c05e503bd136ff3ea0257"), "name" : "小明" }
{ "_id" : ObjectId("598c0b0603bd136ff3ea0258"), "name" : "zhangsan" }

> db.user.remove({name:'zhangsan'}) --再删除
WriteResult({ "nRemoved" : 1 })

> db.user.find() --再查询
{ "_id" : ObjectId("598c05e503bd136ff3ea0257"), "name" : "小明" }

7、删除数据库 

db.dropDatabase()

> use delectdb --创建数据库
switched to db delectdb

> db.dropDatabase() --删除数据库
{ "ok" : 1 }

8、帮助 

db.help() -- db.数据库名.help()

MongoDB语法 与 关系型数据库SQL语法 比较

MongoDB语法MySql语法
db.test.find({'name':'foobar'})select * from test where name='foobar'
db.test.find()select * from test
db.test.find({'ID':10}).count()select count(*) from test where ID=10
db.test.find().skip(10).limit(20)select * from test limit 10,20
db.test.find({'ID':{$in:[25,35,45]}})select * from test where ID in (25,35,45)
db.test.find().sort({'ID':-1})select * from test order by ID desc
db.test.distinct('name',{'ID':{$lt:20}})select distinct(name) from test where ID<20
db.test.group({key:{'name':true},cond:{'name':'foo'},reduce:function(obj,prev){prev.msum+=obj.marks;},initial:{msum:0}})select name,sum(marks) from testgroup by name
db.test.find('this.ID<20',{name:1})select name from test where ID<20
db.test.insert({'name':'foobar','age':25})insert into test ('name','age') values('foobar',25)
db.test.remove({})delete * from test
db.test.remove({'age':20})delete test where age<20
db.test.remove({'age':{$lte:20}})delete test where age<=20
db.test.remove({'age':{$gt:20}})delete test where age>20
db.test.remove({'age':{$gte:20}})delete test where age>=20
db.test.remove({'age':{$ne:20}})delete test where age!=20
db.test.update({'name':'foobar'},{$set:{'age':36}})update test set age=36 where name='foobar'
db.test.update({'name':'foobar'},{$inc:{'age':3}})update test set age=age+3 where name='foobar'

模糊查询:$regex

db.test.find({"name":{$regex:"aaa"}})

分组个数过滤

db.getCollection('id_mapper').aggregate([{$group:{ _id :"$contract_id",count:{$sum:1}}},{$match:{count:{$gt:1}}}])

判断是否为空

db.getCollection('id_mapper').find({"sinocardid":{$in:[null]}})

Mongodb 高级查询 --- 多级路径查询 ( 嵌套查询 )

db.getCollection('cinema_portrait').find({"_id":'10100'}, {'portrait.data.124.90天一级品类':1})

{
    "_id" : "10100",
    "portrait" : {
        "data" : {
            "124" : {
                "90天一级品类" : {
                    "食品饮料、酒类、生鲜" : 1.12,
                    "手机、数码" : 0.95,
                    "家用电器" : 0.94,
                    "家具、家具、家装、厨具" : 0.77,
                    "电脑、办公" : 0.57,
                    "母婴、玩具乐器" : 0.57,
                    "服饰内衣、珠宝首饰" : 0.43,
                    "鞋靴、箱包、钟表、奢侈品" : 0.4,
                    "营养保健" : 0.38
                }
            }
        }
    }
}

mongodb 与 mysql 命令对比

来源:https://blog.csdn.net/liuzhoulong/article/details/6825898

传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式自由的特点。

MySQL

MongoDB

说明

mysqld

mongod

服务器守护进程

mysql

mongo

客户端工具

mysqldump

mongodump

逻辑备份工具

mysql

mongorestore

逻辑恢复工具

db.repairDatabase()

修复数据库

mysqldump

mongoexport

数据导出工具

source

mongoimport

数据导入工具

grant * privileges on *.* to …

Db.addUser()

Db.auth()

新建用户并权限

show databases

show dbs

显示库列表

Show tables

Show collections

显示表列表

Show slave status

Rs.status

查询主从状态

Create table users(a int, b int)

db.createCollection("mycoll", {capped:true,

size:100000}) 另:可隐式创建表。

创建表

Create INDEX idxname ON users(name)

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

创建索引

Create INDEX idxname ON users(name,ts DESC)

db.users.ensureIndex({name:1,ts:-1})

创建索引

Insert into users values(1, 1)

db.users.insert({a:1, b:1})

插入记录

Select a, b from users

db.users.find({},{a:1, b:1})

查询表

Select * from users

db.users.find()

查询表

Select * from users where age=33

db.users.find({age:33})

条件查询

Select a, b from users where age=33

db.users.find({age:33},{a:1, b:1})

条件查询

select * from users where age<33

db.users.find({'age':{$lt:33}})

条件查询

select * from users where age>33 and age<=40

db.users.find({'age':{$gt:33,$lte:40}})

条件查询

select * from users where a=1 and b='q'

db.users.find({a:1,b:'q'})

条件查询

select * from users where a=1 or b=2

db.users.find( { $or : [ { a : 1 } , { b : 2 } ] } )

条件查询

select * from users limit 1

db.users.findOne()

条件查询

select * from users where name like "%Joe%"

db.users.find({name:/Joe/})

模糊查询

select * from users where name like "Joe%"

db.users.find({name:/^Joe/})

模糊查询

select count(1) from users

Db.users.count()

获取表记录数

select count(1) from users where age>30

db.users.find({age: {'$gt': 30}}).count()

获取表记录数

select DISTINCT last_name from users

db.users.distinct('last_name')

去掉重复值

select * from users ORDER BY name

db.users.find().sort({name:-1})

排序

select * from users ORDER BY name DESC

db.users.find().sort({name:-1})

排序

EXPLAIN select * from users where z=3

db.users.find({z:3}).explain()

获取存储路径

update users set a=1 where b='q'

db.users.update({b:'q'}, {$set:{a:1}}, false, true)

更新记录

update users set a=a+2 where b='q'

db.users.update({b:'q'}, {$inc:{a:2}}, false, true)

更新记录

delete from users where z="abc"

db.users.remove({z:'abc'})

删除记录

db. users.remove()

删除所有的记录

drop database IF EXISTS test;

use test

db.dropDatabase()

删除数据库

drop table IF EXISTS test;

db.mytable.drop()

删除表/collection

db.addUser(‘test’, ’test’)

添加用户

readOnly-->false

db.addUser(‘test’, ’test’, true)

添加用户

readOnly-->true

db.addUser("test","test222")

更改密码

db.system.users.remove({user:"test"})

或者db.removeUser('test')

删除用户

mongodb 语法

MongoDB 的好处挺多的,比如多列索引,查询时可以用一些统计函数,支持多条件查询,但是目前多表查询是不支持的,可以想办法通过数据冗余来解决多表查询的问题。

Mongo DB对数据的操作很丰富,下面做一些举例说明,内容大部分来自官方文档,另外有部分为自己理解。

查询 colls 所有数据
//select * from colls
db.colls.find()               

通过指定条件查询
//select * from colls where last_name='Smith'
db.colls.find({'last_name': 'Smith'});    

指定多条件查询
//select * from colls where x=3 and y='foo'
db.colls.find( { x : 3, y : "foo" } );    

指定条件范围查询
//select * from colls where j!=3 and k>10
db.colls.find({j: {$ne: 3}, k: {$gt: 10} }); 

查询不包括某内容
db.colls.find({}, {a:0}); //查询除a为0外的所有数据

支持 <, <=, >, >= 查询,需用符号替代分别为 $lt,$lte,$gt,$gte
db.colls.find({ "field" : { $gt: value } } );
db.colls.find({ "field" : { $lt: value } } );
db.colls.find({ "field" : { $gte: value } } );
db.colls.find({ "field" : { $lte: value } } );

也可对某一字段做范围查询
db.colls.find({ "field" : { $gt: value1, $lt: value2 } } );

不等于查询用字符$ne
db.colls.find( { x : { $ne : 3 } } );

in查询用字符$in
db.colls.find( { "field" : { $in : array } } );
db.colls.find({j:{$in: [2,4,6]}});

not in查询用字符$nin
db.colls.find({j:{$nin: [2,4,6]}});

取模查询用字符$mod
db.colls.find( { a : { $mod : [ 10 , 1 ] } } )  // where a % 10 == 1

$all查询
db.colls.find( { a: { $all: [ 2, 3 ] } } );  //指定a满足数组中任意值时

$size查询
//对对象的数量查询,此查询查询a的子对象数目为1的记录
db.colls.find( { a : { $size: 1 } } ); 

$exists查询
db.colls.find( { a : { $exists : true } } );  // 存在a对象的数据
db.colls.find( { a : { $exists : false } } ); // 不存在a对象的数据

$type查询 $type值为 bsonhttp://bsonspec.org/ 数据的类型值
db.colls.find( { a : { $type : 2 } } );  // 匹配a为string类型数据
db.colls.find( { a : { $type : 16 } } ); // 匹配a为int类型数据

使用正则表达式匹配
db.colls.find( { name : /acme.*corp/i } ); //类似于SQL中like

内嵌对象查询
db.colls.find( { "author.name" : "joe" } );

1.3.3版本及更高版本包含$not查询
db.colls.find( { name : { $not : /acme.*corp/i } } );
db.colls.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );

sort()排序
db.colls.find().sort( { ts : -1 } ); //1为升序2为降序

limit()对限制查询数据返回个数
db.colls.find().limit(10)

skip()跳过某些数据
db.colls.find().skip(10)

snapshot()快照保证没有重复数据返回或对象丢失

count()统计查询对象个数
db.students.find({'address.state' : 'CA'}).count();  //效率较高
db.students.find({'address.state' : 'CA'}).toArray().length;  //效率很低

group()对查询结果分组和SQL中group by函数类似
distinct()返回不重复值

MongoDB GUI( Robo 3T) Shell使用及操作

From:http://www.cnblogs.com/dacongge/p/7346037.html

Robo 3T 下载及使用

之前叫 Robomongo,后面被收购了,改名 Robo 3T 。

下载链接:https://robomongo.org

安装步骤省略,下一步下一步...

图形界面,连接默认,取个名字就行。

连接成功,可以愉快的使用了,不用总是敲命令了,简洁方便,多种显示。

软件右边可以切换显示样式,慢慢折腾。

Robo 3T Shell 操作

右键数据库打开Shell

下面玩一下没用的语法,绿色按钮为运行命令。

1、批量插入(默认是不支批量操作,只能用for循环。)

2、$type 操作符,基于BSON类型来检索集合中匹配的数据类型,并返回结果。

先增加一些数据,然后查询出来 (同一界面,需要选中执行的一行,不然会一直执行第一个命令。)

3、Limit与Skip的用法

查询文档中两条记录

  • 第一个 {} 放 where 条件,为空表示返回集合中所有文档。
  • 第二个 {} 指定那些列显示和不显示 (0表示不显示 1表示显示)。

查询显示第2、3条文档数据

  • skip()方法默认参数为 0 。
  • skip 和 limit 结合就能实现分页。

排序 sort() 方法

索引 ensureIndex() 方法

  • 多个字段索引:db.student.ensureIndex({"name":1,"hobby":-1})

聚合 aggregate()

这里只操作一种方法,分组并统计,其它的可以查看相关用法和文档。

总结:常用的一些基本用法就这些,高级用法可以慢慢再研究。说实话这个工具挺实用的,还有些智能提示,不用天天对着一个黑框,哈哈。接下开始实战。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值