2018-09-12 小白必须懂的`MongoDB`的十大总结

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

小白必须懂的MongoDB的十大总结

一、MongoDB的认识

1、什么是 MongoDB

MongoDB 是一个介于关系数据库和非关系数据库之间的开源产品,是最接近于关系型数据库的 NoSQL 数据库。它在轻量级JSON 交换基础之上进行了扩展,即称为 BSON 的方式来描述其无结构化的数据类型。尽管如此它同样可以存储较为复杂的数据类型。它和上一篇文章讲到的Redis有异曲同工之妙。虽然两者均为 NoSQL ,但是 MongoDB 相对于 Redis 而言,MongoDB 更像是传统的数据库。早些年我们是先有了 Relation Database (关系型数据库),然后出现了很多很复杂的query ,里面用到了很多嵌套,很多 join 操作。所以在设计数据库的时候,我们也考虑到了如何应用他们的关系,使得写 query 可以使 database 效率达到最高。后来人们发现,不是每个系统,都需要如此复杂的关系型数据库。有些简单的网站,比如博客,比如社交网站,完全可以斩断数据库之间的一切关系。这样做带来的好处是,设计数据库变得更加简单,写 query 也变得更加简单。然后,query 消耗的时间可能也会变少。因为 query 简单了,少了许多消耗资源的 join 操作,速度自然会上去。正如所说的, query 简单了,很有以前 MySQL 可以找到的东西,现在关系没了,通过 Mongo 找不到了。我们只能将几组数据都抓到本地,然后在本地做 join ,所以在这点上可能会消耗很多资源。这里我们可以发现。如何选择数据库,完全取决于你所需要处理的数据的模型,即 Data Model 。如果它们之间,关系错综复杂,千丝万缕,这个时候 MySQL 一定是首选。如果他们的关系并不是那么密切,那么, NoSQL 将会是利器。

MongoDBRedis 一样均为 key-value 存储系统,它具有以下特点:

  • 面向集合存储,易存储对象类型的数据。

  • 模式自由。

  • 支持动态查询。

  • 支持完全索引,包含内部对象。

  • 支持查询。

  • 支持复制和故障恢复。

  • 使用高效的二进制数据存储,包括大型对象(如视频等)。

  • 自动处理碎片,以支持云计算层次的扩展性

  • 支持 PythonPHPRubyJavaCC#JavascriptPerlC++ 语言的驱动程序,社区中也提供了对 Erlang.NET 等平台的驱动程序。

  • 文件存储格式为 BSON (一种 JSON 的扩展)。

  • 可通过网络访问。

2、MongoDBMySQL 性能比较

MySQL 一样, MongoDB 提供了丰富的远远超出了简单的键值存储中提供的功能和功能。 MongoDB 具有查询语言,功能强大的辅助索引(包括文本搜索和地理空间),数据分析功能强大的聚合框架等。相比使用关系数据库而言,使用MongoDB ,您还可以使用如下表所示的这些功能,跨越更多样化的数据类型和数据规模。

MySQL MongoDB
丰富的数据模型
动态 Schema
数据类型
数据本地化
字段更新
易于编程
复杂事务
审计
自动分片

MySQL 中的许多概念在 MongoDB 中具有相近的类比。本表概述了每个系统中的一些常见概念。

MySQL MongoDB
集合
文档
字段
joins 嵌入文档或者链接

3、应用范围和限制

MongoDB 的主要目标是在 key-value (键/值)存储方式(提供了高性能和高度伸缩性)以及传统的 RDBMS 系统(丰富的功能)架起一座桥梁,集两者的优势于一身。 MongoDB 适用范围如下:

  • 网站数据: Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。

  • 缓存:由于性能很高, Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由 Mongo 搭建的持久化缓存层可以避免下层的数据源过载。

  • 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。

  • 高伸缩性的场景: Mongo 非常适合由数十或数百台服务器组成的数据库。 Mongo 的路线图中已经包含对 MapReduce 引擎的内置支持。

  • 用于对象及 JSON 数据的存储: MongoBSON 数据格式非常适合文档化格式的存储及查询。

MongoDB 当然也会有以下场景的限制:

  • 高度事物性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。

  • 传统的商业智能应用:针对特定问题的 BI 数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。

  • 需要 SQL 的问题。

二、MongoDB 的安装

环境准备

安装步骤

1、创建一个 mongodb-org-3.6.repo 文件
vi /etc/yum.repos.d/mongodb-org-3.6.repo

在文件中加入如下内容:

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

退出编辑模式,直接输入如下命令安装即可:

sudo yum install -y mongodb-org

C:Users87328DesktopMongoDB�

若要安装特定版本的 MongoDB ,请分别指定每个组件包并将版本号附加到包名称,如下所示:

sudo yum install -y mongodb-org-3.6.3 mongodb-org-server-3.6.3 mongodb-org-shell-3.6.3 mongodb-org-mongos-3.6.3 mongodb-org-tools-3.6.3

你可以指定任何可用的 MongoDB 版本。然而, yum 会在新版本可用时升级软件包。为防止意外升级,请钉住包装。要固定软件包,请将以下 exclude 指令添加到 /etc/yum.conf 文件中:

exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools

我们直接运行如下命令:

mongod -repair

看到如下字样,说明我们安装成功!


C:Users87328DesktopMongoDB�

我们创建一个 db ,并查看下 mongo 的安装位置:

C:Users87328DesktopMongoDB�

mkdir db
whereis mongod

安装完成后启动 mongodb ,并查看下 mongob 启动状态:

systemctl start mongod.service
systemctl status mongod.service

如果出现如下字样,说明启动成功!


C:Users87328DesktopMongoDB�

成功启动 MongoDB 后,新建一个命令行输入 mongo 进行登录操作,即可进行数据库的一些操作了。

mongo

C:Users87328DesktopMongoDB�

三、MongoDB 数据类型及常用命令讲解

MongoDB 的数据类型大致有下列几种:

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

下面我们将介绍一些 MongoDB 的常用命令!

1、创建数据库

use 数据库名称 :创建一个新的数据库。注意:如果该数据库不存在,则创建,如果该数据库存在,则是切换
如果创建了数据库,没有任何的操作,则会自动删除该数据库

example:

> use stu
switched to db stu

2、查看数据库

show dbs :查看当前有多少个数据库

example:

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

3、创建集合

db.集合名.insert({}) :向集合里面,添加文档。{} 里面是 json 的文档。注意: mongodb 里面的集合是隐式创建,就是无需创建,直接使用。 db 表示显示当前所在的数据库。

example:

> db.php.insert({"name":"xiaoming","age":20,"email":"xiaoming@gmail.com"})
WriteResult({ "nInserted" : 1 })
> db.php.insert({"name":"xiaohong","age":18,"email":"xiaohong@gmail.com"})
WriteResult({ "nInserted" : 1 })

4、查看集合

show tables :查看当前数据库中的集合

example:

> show tables
php

5、查询集合里面的文档

db.集合名.find() :查询当前数据库中该集合下的所有文档

example:

> db.php.find()
{ "_id" : ObjectId("5b9318ac487b851e62879578"), "name" : "xiaoming", "age" : 20, "email" : "xiaoming@gmail.com" }
{ "_id" : ObjectId("5b9319a2487b851e62879579"), "name" : "xiaohong", "age" : 18, "email" : "xiaohong@gmail.com" }

db.集合名.find :查询当前数据库中该集合下的第一个文档

example:

> db.php.find
function (query, fields, limit, skip, batchSize, options) {
    var cursor = new DBQuery(this._mongo,
                             this._db,
                             this,
                             this._fullName,
                             this._massageObject(query),
                             fields,
                             limit,
                             skip,
                             batchSize,
                             options || this.getQueryOptions());

    {
        const session = this.getDB().getSession();

        const readPreference = session._serverSession.client.getReadPreference(session);
        if (readPreference !== null) {
            cursor.readPref(readPreference.mode, readPreference.tags);
        }

        const readConcern = session._serverSession.client.getReadConcern(session);
        if (readConcern !== null) {
            cursor.readConcern(readConcern.level);
        }
    }

    return cursor;
}

6、删除集合

db.集合名.drop() :删除当前数据库中的集合

example:

> db.php.drop()
true

7、删除数据库

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

> db.dropDatabase()
{ "dropped" : "stu", "ok" : 1 }

8、帮助命令

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                 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() :数据库相关的帮助命令

example:

> db.help()
DB methods:
    db.adminCommand(nameOrDocument) - switches to 'admin' db, and runs command [just calls db.runCommand(...)]
    db.aggregate([pipeline], {options}) - performs a collectionless aggregation on this database; returns a cursor
    db.auth(username, password)
    db.cloneDatabase(fromhost)
    db.commandHelp(name) returns the help for the command
    db.copyDatabase(fromdb, todb, fromhost)
    db.createCollection(name, {size: ..., capped: ..., max: ...})
    db.createView(name, viewOn, [{$operator: {...}}, ...], {viewOptions})
    db.createUser(userDocument)
    db.currentOp() displays currently executing operations in the db
    db.dropDatabase()
    db.eval() - deprecated
    db.fsyncLock() flush data to disk and lock server for backups
    db.fsyncUnlock() unlocks server following a db.fsyncLock()
    db.getCollection(cname) same as db['cname'] or db.cname
    db.getCollectionInfos([filter]) - returns a list that contains the names and options of the db's collections
    db.getCollectionNames()
    db.getLastError() - just returns the err msg string
    db.getLastErrorObj() - return full status object
    db.getLogComponents()
    db.getMongo() get the server connection object
    db.getMongo().setSlaveOk() allow queries on a replication slave server
    db.getName()
    db.getPrevError()
    db.getProfilingLevel() - deprecated
    db.getProfilingStatus() - returns if profiling is on and slow threshold
    db.getReplicationInfo()
    db.getSiblingDB(name) get the db at the same server as this one
    db.getWriteConcern() - returns the write concern used for any operations on this db, inherited from server object if set
    db.hostInfo() get details about the server's host
    db.isMaster() check replica primary status
    db.killOp(opid) kills the current operation in the db
    db.listCommands() lists all the db commands
    db.loadServerScripts() loads all the scripts in db.system.js
    db.logout()
    db.printCollectionStats()
    db.printReplicationInfo()
    db.printShardingStatus()
    db.printSlaveReplicationInfo()
    db.dropUser(username)
    db.repairDatabase()
    db.resetError()
    db.runCommand(cmdObj) run a database command.  if cmdObj is a string, turns it into {cmdObj: 1}
    db.serverStatus()
    db.setLogLevel(level,)
    db.setProfilingLevel(level,slowms) 0=off 1=slow 2=all
    db.setWriteConcern() - sets the write concern for writes to the db
    db.unsetWriteConcern() - unsets the write concern for writes to the db
    db.setVerboseShell(flag) display extra information in shell output
    db.shutdownServer()
    db.stats()
    db.version() current version of the server

db.集合名.help() :集合相关的帮助命令

example:

> db.php.help()
DBCollection help
    db.php.find().help() - show DBCursor help
    db.php.bulkWrite( operations,  ) - bulk execute write operations, optional parameters are: w, wtimeout, j
    db.php.count( query = {},  ) - count the number of documents that matches the query, optional parameters are: limit, skip, hint, maxTimeMS
    db.php.copyTo(newColl) - duplicates collection by copying all documents to newColl; no indexes are copied.
    db.php.convertToCapped(maxBytes) - calls {convertToCapped:'php', size:maxBytes}} command
    db.php.createIndex(keypattern[,options])
    db.php.createIndexes([keypatterns], )
    db.php.dataSize()
    db.php.deleteOne( filter,  ) - delete first matching document, optional parameters are: w, wtimeout, j
    db.php.deleteMany( filter,  ) - delete all matching documents, optional parameters are: w, wtimeout, j
    db.php.distinct( key, query,  ) - e.g. db.php.distinct( 'x' ), optional parameters are: maxTimeMS
    db.php.drop() drop the collection
    db.php.dropIndex(index) - e.g. db.php.dropIndex( "indexName" ) or db.php.dropIndex( { "indexKey" : 1 } )
    db.php.dropIndexes()
    db.php.ensureIndex(keypattern[,options]) - DEPRECATED, use createIndex() instead
    db.php.explain().help() - show explain help
    db.php.reIndex()
    db.php.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to return.
                                                  e.g. db.php.find( {x:77} , {name:1, x:1} )
    db.php.find(...).count()
    db.php.find(...).limit(n)
    db.php.find(...).skip(n)
    db.php.find(...).sort(...)
    db.php.findOne([query], [fields], [options], [readConcern])
    db.php.findOneAndDelete( filter,  ) - delete first matching document, optional parameters are: projection, sort, maxTimeMS
    db.php.findOneAndReplace( filter, replacement,  ) - replace first matching document, optional parameters are: projection, sort, maxTimeMS, upsert, returnNewDocument
    db.php.findOneAndUpdate( filter, update,  ) - update first matching document, optional parameters are: projection, sort, maxTimeMS, upsert, returnNewDocument
    db.php.getDB() get DB object associated with collection
    db.php.getPlanCache() get query plan cache associated with collection
    db.php.getIndexes()
    db.php.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )
    db.php.insert(obj)
    db.php.insertOne( obj,  ) - insert a document, optional parameters are: w, wtimeout, j
    db.php.insertMany( [objects],  ) - insert multiple documents, optional parameters are: w, wtimeout, j
    db.php.mapReduce( mapFunction , reduceFunction ,  )
    db.php.aggregate( [pipeline],  ) - performs an aggregation on a collection; returns a cursor
    db.php.remove(query)
    db.php.replaceOne( filter, replacement,  ) - replace the first matching document, optional parameters are: upsert, w, wtimeout, j
    db.php.renameCollection( newName ,  ) renames the collection.
    db.php.runCommand( name ,  ) runs a db command with the given name where the first param is the collection name
    db.php.save(obj)
    db.php.stats({scale: N, indexDetails: true/false, indexDetailsKey: , indexDetailsName: })
    db.php.storageSize() - includes free space allocated to this collection
    db.php.totalIndexSize() - size in bytes of all the indexes
    db.php.totalSize() - storage allocated for all data and indexes
    db.php.update( query, object[, upsert_bool, multi_bool] ) - instead of two flags, you can pass an object with fields: upsert, multi
    db.php.updateOne( filter, update,  ) - update the first matching document, optional parameters are: upsert, w, wtimeout, j
    db.php.updateMany( filter, update,  ) - update all matching documents, optional parameters are: upsert, w, wtimeout, j
    db.php.validate(  ) - SLOW
    db.php.getShardVersion() - only for use with sharding
    db.php.getShardDistribution() - prints statistics about data distribution in the cluster
    db.php.getSplitKeysForChunks(  ) - calculates split points over all chunks and returns splitter function
    db.php.getWriteConcern() - returns the write concern used for any operations on this collection, inherited from server/db if set
    db.php.setWriteConcern(  ) - sets the write concern for writes to the collection
    db.php.unsetWriteConcern(  ) - unsets the write concern for writes to the collection
    db.php.latencyStats() - display operation latency histograms for this collection

四、增删改查操作

1、添加文档

db.集合名.insert({k1:v1,k2:v2...}) :向当前数据库的该集合下添加文档

我们在添加文档的时候有如下注意点:

a) 文档就是键值对,数据类型是 BSON 格式,支持的值更加丰富。 BSONJSON 的扩展,新增了诸如日期,浮点等 JSON 不支持的数据类型。

b) 在添加的文档里面,都有一个 '_id' 的键,值为对象类型 ObjectID ,在这里,我们解释下 ObjectID 类型:

每个文档都有一个 _id 字段,并且同一集合中的 _id 值唯一,该字段可以是任意类型的数据,默认是一个 ObjectID 对象。
ObjectID 对象数据组成:时间戳|机器码|PID|计数器
_id 的键值我们可以自己输入,但是不能重复,但要注意的一点是在插入数据的时候,如果 _id 的值重复则会报错

c) 可以使用 js 代码来完成批量插入文档

example:

> for(var i=1;i<=10;i++){
... db.php.insert({'name':'xiaobai'+i,'age':i,'email':'xiaobai'+i+'@gmail.com'})
... }
WriteResult({ "nInserted" : 1 })
> db.php.find()
{ "_id" : ObjectId("5b931b74a39e4f4842ba36b3"), "name" : "xiaoming", "age" : 20, "email" : "xiaoming@gmail.com" }
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaohong", "age" : 18, "email" : "xiaohong@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36b5"), "name" : "xiaobai1", "age" : 1, "email" : "xiaobai1@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36b6"), "name" : "xiaobai2", "age" : 2, "email" : "xiaobai2@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36b7"), "name" : "xiaobai3", "age" : 3, "email" : "xiaobai3@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36b8"), "name" : "xiaobai4", "age" : 4, "email" : "xiaobai4@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36b9"), "name" : "xiaobai5", "age" : 5, "email" : "xiaobai5@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "name" : "xiaobai6", "age" : 6, "email" : "xiaobai6@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "name" : "xiaobai7", "age" : 7, "email" : "xiaobai7@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bc"), "name" : "xiaobai8", "age" : 8, "email" : "xiaobai8@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "name" : "xiaobai9", "age" : 9, "email" : "xiaobai9@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36be"), "name" : "xiaobai10", "age" : 10, "email" : "xiaobai10@gmail.com" }

2、删除文档

db.集合名.remove{(条件)} :删除当前数据库下指定集合中满足条件的文档(不写条件则删除所有的文档)

example:

> db.php.remove({age:20})
WriteResult({ "nRemoved" : 1 })
> db.php.remove({age:{'$lt':6}})
WriteResult({ "nRemoved" : 5 })
> db.php.find()
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaohong", "age" : 18, "email" : "xiaohong@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "name" : "xiaobai6", "age" : 6, "email" : "xiaobai6@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "name" : "xiaobai7", "age" : 7, "email" : "xiaobai7@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bc"), "name" : "xiaobai8", "age" : 8, "email" : "xiaobai8@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "name" : "xiaobai9", "age" : 9, "email" : "xiaobai9@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36be"), "name" : "xiaobai10", "age" : 10, "email" : "xiaobai10@gmail.com" }

这里我们在删除 php 集合中年龄小于6的文档时,我们使用了操作符来完成。

比较运算符

操作符 效果
$gt 大于
$lt 小于
$gte 大于等于
$lte 小于等于
$exists 存在与否
$in 包含
$ne 不等于
$nin 不包含

逻辑运算符

操作符 效果
$exists 存在与否
$or 或者
$and 并且
$not 不存在
$mod 求模
$where 位置

特别的 $exists: true 表示字段存在

排序 sort

操作 效果
$asc 升序
$desc 降序
3、更新文档

更新文档有两种方式进行修改

方法一、直接修改

db.集合名.update({条件},{新的文档}) :修改当前数据库下指定集合中满足条件的文档信息

example:

> db.php.find()
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaohong", "age" : 18, "email" : "xiaohong@gmail.com" }
> db.php.update({age:18},{name:'xiaobai5'})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.php.find()
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaobai5" }

db.集合.update(条件,新文档,是否新增,是否修改多条) :修改当前数据库下指定集合中满足条件的文档信息

  • 是否新增:如果值是1(true)则没有满足条件的 则添加

  • 是否修改多条:若值是1(true),如果满足条件的有多个文档 则都要修改

example:

> db.php.update({age:10},{name:'xiaoli'},true,true)
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 9,
        "errmsg" : "multi update only works with $ operators"
    }
})

方法二、使用修改器

example:

我们要修改 age=6 的文档名称为 xiaosan ,并且其他键值不能丢失

我们可以使用修改器

  • $inc :加上一个数字

  • $set :修改某一个字段,如果该字段不存在就增这个字段

语法:db.集合名.update({条件},{修改器名称:{修改的键:修改的新值}})

> db.php.update({age:6},{'$set':{name:'xiaosan'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

那如果我们要修改 age=10 的文档的年龄增加十岁,我们可以这样做:

> db.php.update({age:10},{$inc:{age:10}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

4、查询文档

语法: db.集合名.find({条件})

example:

取出 php 集合里面的第一个文档

> db.php.findOne()
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaobai5" }

取出 php 集合里面 age=6 的文档

> db.php.find({age:6})
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "name" : "xiaosan", "age" : 6, "email" : "xiaobai6@gmail.com" }

取出 php 集合里面 age>8 的文档

> db.php.find({age:{'$gt':8}})
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "name" : "xiaobai9", "age" : 9, "email" : "xiaobai9@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36be"), "name" : "xiaobai10", "age" : 20, "email" : "xiaobai10@gmail.com" }

取出 php 集合里面的文档,只显示 name

> db.php.find({},{age:1})//1表示只显示age键值
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4") }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "age" : 6 }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "age" : 7 }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bc"), "age" : 8 }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "age" : 9 }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36be"), "age" : 20 }
> db.php.find({},{age:0})//1表示除了显示age键值,其他的都显示
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaobai5" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "name" : "xiaosan", "email" : "xiaobai6@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "name" : "xiaobai7", "email" : "xiaobai7@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bc"), "name" : "xiaobai8", "email" : "xiaobai8@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "name" : "xiaobai9", "email" : "xiaobai9@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36be"), "name" : "xiaobai10", "email" : "xiaobai10@gmail.com" }

根据年龄的(降序|升序)来显示文档

db.集合名.find().sort({age:1})根据年龄升序
db.集合名.find().sort({age:0})根据年龄降序

显示 php 集合中的前三个文档

> db.php.find().limit(3)
{ "_id" : ObjectId("5b931b7ca39e4f4842ba36b4"), "name" : "xiaobai5" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36ba"), "name" : "xiaosan", "age" : 6, "email" : "xiaobai6@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "name" : "xiaobai7", "age" : 7, "email" : "xiaobai7@gmail.com" }

显示 php 集合中的第三个文档到第五个文档

> db.php.find().skip(2).limit(3)
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bb"), "name" : "xiaobai7", "age" : 7, "email" : "xiaobai7@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bc"), "name" : "xiaobai8", "age" : 8, "email" : "xiaobai8@gmail.com" }
{ "_id" : ObjectId("5b931dfba39e4f4842ba36bd"), "name" : "xiaobai9", "age" : 9, "email" : "xiaobai9@gmail.com" }

统计 php 集合中文档的个数

db.集合名.count():返回集合中有多少个文档

五、用户管理(权限控制)

1、权限概述

MongoDB 里面的用户是属于数据库的,每个数据库都有自己的管理员。管理员登录后,只能操作所属的数据库。注意:在 admin 的数据库中创建的用户是超级管理员,登陆后可以操作任何的数据库

2、创建用户

(1) 选择数据库

use 数据库的名称

(2) 添加用户

db.createUser(用户名,密码,是否只读)

第三个参数"是否只读"默认是 false ,创建的用户可以执行读写,如果是 true,则创建的用户只能查询,不能修改。

注意点:在创建用户之前,必须先创建一个超级管理员

example:

> use admin
switched to db admin
> db.createUser({user:'user',
...  pwd:'passwd', 
...  roles:[
...    {role:'userAdminAnyDatabase', db:'admin'}
... ]
... })
Successfully added user: {
    "user" : "user",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}

3、验证权限(用户登录)

在添加完成管理员之后,我们做如下操作:

(1) 如果你是安装成windows服务的方式安装的,则卸载服务,在安装时添加一个 -auth 选项,auth 表示要开启权限认证

(2) 如果你是直接启动的方式,则停止服务,重新启动,在启动时也要添加 --auth 选项,auth 表示要开启权限认证

如果没有通过权限验证,直接操作数据库,则报如下错误提示:

error: {
       "$err" : "unauthorized db:test lock type:-1 client:127.0.0.1",
        "code" : 10057
}

如何通过权限验证

  1. 选择数据库

  2. 执行db.auth (用户名,密码)

4、删除用户和修改密码

注意:创建的用户名和密码是存储在各自数据库里面的 system.users 集合里面的。想要删除用户,则直接删除 system.users 集合里面的文档即可

5、总结说明

a) 非 admin 数据库的用户不能使用数据库命令,比如 show dbs

(b) admin 数据库中的用户被视为超级用户(即管理员),在认证之后,管理员可以读写所有数据库,执行特定的管理命令。

© 在开启安全检查之前,一定要至少有个管理员账户。

(d) 数据库的用户账号以文档的形式存储在 system.users 集合里面。可以在 system.users 集合中删除用户账号文档,就可以删除用户。

六、MongoDB中的索引

1、普通单列索引

我们用如下代码来测试:

for(var i=0;i<200000;i++){
    db.java.insert({name:'xiao'+i,age:i})
}

第一、我们先检验一下查询性能

var start=new Date()
db.java.find({name:'xiao156789'})
var end=new Date()
end-start
17510

第二、为 name 创建索引

> db.java.ensureIndex({name:1})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

第三、再执行第一部分代码可以看出有数量级的性能提升

语法:db.集合名.ensureIndex({键名:1}) :1是升序,-1是降序

2、多列索引(复合索引)

创建多列索引
语法:db.集合名.ensureIndex({field1:1/-1,field2:1/-1})
nameage 建立一个复合索引,可以使用 db.集合名.getIndexes() 查看创建的索引情况

3、子文档索引

语法: db.集合名.ensureIndex({field.subfield:1/-1})
如下文档可以建立子文档索引

{name:'诺基亚手机1',price:12.34,spc:{weight:100,area:'纽约'}}
{name:'诺基亚手机2',price:42.34,spc:{weight:200,area:'伦敦'}}

比如要查询 weight=100 的文档

db.goods.find({'spc.weight':100})

根据当前案例,我们建立子文档索引

db.net.ensureIndex({'spc.w':1})

4、唯一索引

语法: db.集合名.ensureIndex({name:-1},{unique:true})

5、查看索引

(1) 查看当前索引状态: db.集合名.getIndexes()

(2) 详情查看本次查询使用哪个索引和查询数据的状态信息: db.集合名.find({name:''xiao}).explain()

6、删除索引

删除单个索引: db.集合名.dropIndex({filed:1/-1})

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

7、重建索引

一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此,可以通过索引的重建,减少索引文件碎片,并提高索引的效率,类似 mysql 中的 optimize table

mysql 里面使用 optimize table 语法: optimize table 表名

语法: db.集合名.reIndex()

8、索引使用注意事项

(1) 创建索引的时候,注意1是正序创建索引,-1是倒序创建索引

(2) 索引的创建在提高查询性能的同时会影响插入性能,对于经常查询少插入

(3) 复合索引要注意索引的先后顺序

(4) 每个键全建立索引不一定就能提高性能,索引不是万能的。

(5) 在做排序工作的时候如果是超大数据量也可以考虑加上索引用来提高排序的性能。

八、MongoDB中的数据导出与导出

利用mongoexport

  • -h host主机

  • -port 端口

  • -d 指明使用的库

  • -o 指明要导出的文件名

  • -csv 指定导出的csv格式

  • -q 过滤导出

  • -f field1 field2 列名

  • -u username 用户名

  • -p password 密码

注意:在使用用户名和密码是超级管理员的时候,如果端口是默认的可以不使用-port来指定端口

(2) 导入数据

  • -d 待导入的数据库

  • -c 待导入的集合(不存在会自己创建)

  • -type csv/json(默认)

  • -file 备份文件路径

例如:导入json

./bin/mongoimport -h -port 端口号 -d test -c goods -file ./goodsall.json

导入csv

./bin/mongoimport -h -port 端口号 -d test -c goods -type csv -f goods.id,goods.name -file ./goodsall.csv

./bin/mongoimport -h -port 端口号 -d test -c goods -type csv -f -headline -f goods.id,goods.name -file ./goodsall.csv

九、主从复制(读写分离)

主从复制是一个简单的数据库同步备份的集群技术,至少两台数据库服务器,可以分别设置主服务器和从服务器,对主服务器的任何操作都会同步到从服务器上。


C:Users87328DesktopMongoDB主从1
C:Users87328DesktopMongoDB主从2

实现的注意点

1、在数据库集群中要明确的知道谁是主服务器,主服务器只有一台

2、从服务器要知道自己的数据源 也就是对应的主服务是谁

3、–master用来确定主服务器 --slave和–source来控制从服务器

配置步骤

(1) 启动主服务器

(2) 启动从服务器

(3) 客户端登录到主服务器

添加一些数据,测试是否同步到从服务器,在主服务器里面,添加了一些文档:

第一步,客户端登录到主服务器,添加一些文档

第二步,登录到从服务器,查看是否有数据,如果有数据,则成功了!

十、php操作MongoDB

1、安装扩展

注意:扩展文件,下载合适的php_mongodb.dll文件

  1. php的版本

  2. 是否是线程安全的thread safe(ts)

  3. 是vc几的

  4. php是32位的还是64位的

步骤

  1. 把对应的扩展,拷贝到PHP的安装目录里面的ext目录下面,注意:拷贝后改名为php_mongo.dll,方便管理

  2. 打开php.ini文件,引入该扩展

extension=php_mongo.dll

  1. 重启Apache,使用phpinfo()函数测试

2、入门使用

  1. 连接mongodb服务器
$m=new MongoClient("mongodb://root:root@localhost:8888/admin");
$db=$m->selectDb("stu");//选择数据库

  1. 增删改查用法

增删改查

注意,在命令行里面的"." 变成了"->","{}"变成了数组

a) 添加一个文档

$db->php->insert(array('name'=>'李元霸','age'=>12));

b) 查询文档

$data=$db->php->find();

查询年龄等于9的文档:

$data=$db->php->find(array('age'=>9));

查询年龄大于9的文档:

//db.php.find({age:{'$gt':9}})
$data=$db->php->find(array('age'=>array('$gt':9)));

根据年龄降序显示:

$data=$db->php->find()->sort(array('age'=>1));
foreach($data as $v){
    echo $v['name'].'----'.$v['age'].'--'.$v['email'].'';
}

c) 修改文档,我们直接使用修改器来完成

把年龄等于8的名称改名为李白:

//db.php.update({age:8},{'$set':{'name':'李白'}})
$db->php->update(array('age'=>8),array('$set'=>array('name'=>'李白'));

d) 删除文档

比如删除年龄等于10的文档:

//db.php.remove({age:10})
$db->php->remove(array('age'=>10))
$data=$db->php->find()
foreach($data as $v){
    echo $v['name'].'----'.$v['age'].'--'.$v['email'].'';
}

  1. 把mysql表里面的数据存储到mongodb里面
selectDb("stu");//选择数据库
//从mysql里面取出数据
$conn=mysql_connect('localhost','root','root');
mysql_query('use shop');
mysql_query('set names utf8');
$sql="select * from goods";
$res=mysql_query($sql);
while($row=mysql_fetch_assoc($res)){
    $db->goods->insert($row);
}
echo 'ok';
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • NoSql数据库优缺点 在优势方面主要体现在下面几点: 简单的扩展 快速的读写 低廉的成本 灵活的数据模型 在不足...
    dreamer_lk阅读 2,701评论 0 6
  • 一、MongoDB简介 1.概述 ​ MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。旨在为WE...
    郑元吉阅读 974评论 0 2
  • 1. MongoDB 简介 MongoDB是一个可扩展的高性能,开源,模式自由,面向文档的NoSQL,基于分布式文...
    rhlp阅读 1,100评论 0 3
  • Mongodb数据库 [if !supportLists]1.[endif]课程介绍 [if !supportLi...
    6e5e50574d74阅读 840评论 0 0
  • 今天写首不算诗的诗~ 我们都是黑夜里挣扎的晨曦,无奈,赶不走夜…… 无限的遐思, 盘踞于灵魂沉甸的躯壳之下, 傍晚...
    若水忆风阅读 314评论 3 3