小白必须懂的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、MongoDB与MySQL性能比较

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

若要安装特定版本的 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

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

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

mkdir db
whereis mongod

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

systemctl start mongod.service
systemctl status mongod.service

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

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

mongo

三、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 数据库中的用户被视为超级用户(即管理员),在认证之后,管理员可以读写所有数据库,执行特定的管理命令。

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

(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

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

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

实现的注意点

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';

小白必须懂的MongoDB的十大总结的更多相关文章

  1. 看完它,你就全懂了十大Wifi芯片原厂!

    看完它,你就全懂了十大Wifi芯片原厂!   来源:全球物联网观察 概要:不知不觉中,WiFi几乎已攻占了整个世界.现在只要你上网,可能就离不开WiFi了. 2014年是物联网WiFi市场关键的转折期 ...

  2. 十大技巧快速提升原生APP开发性能

    移动应用市场用户争夺战日益激烈,原来做APP拼想法拼创意拼是否抓住用户痛点.现在,精细化用户体验成为了一个APP能否留存用户的关键问题,一旦用户觉得体验不畅,马上就有竞品APP后补,如何开发高性能的移 ...

  3. IT项目经理应具备的十大软技能

    现在,企业对IT部项目经理的要求越来越多.如果你认为IT项目成员只需要技术性能力,那可就错了. 据IT招聘公司调查发现,几年人们对项目管理软技能的兴趣明显浓厚起来.许多企业尽量避免把IT部门看成只是成 ...

  4. node.js之十大Web框架

    之前接触过Node.js是因为好奇大前端越来越能干了,连我后台的饭碗都要抢了,太嚣张了,于是我想打压打压它,然后就这样接触它了.再到后来是因为Settings-Sync插件二次开发,我需要用node. ...

  5. ios审核过程十大常见被拒问题

    欢迎加入ios马甲包经验交流群,群聊号码:744520623 2018年伊始,苹果并没有因为新年的气氛而对CP们“网开一面”.频繁锁榜.调整排名规则以及关键词覆盖算法……不断抛出的大动作,让CP们叫苦 ...

  6. IPv6 优于 IPv4 的十大功能

    现在是 9102 年,有一个严重的问题,困扰着资深宅男二狗子.那就是偶像团体没新名了.今年开始,偶像团体 XKB48 已经在无法取更多的新名字了,排列组合的所有方式都已经经过了历史长河的洗礼,除非偶像 ...

  7. 小白开学Asp.Net Core 《十》

    小白开学Asp.Net Core <十> — — Session.Cookie.Cache(老生常谈) 一.背景 在常谈Session和Cookie之前我们先来简单的了解下Http(可以说 ...

  8. 2019年十大开源WEB应用防火墙点评

    2019年十大开源WEB应用防火墙点评 随着WEB应用的爆炸式成长和HTTPS加密的普及,针对网络应用层的攻击,像SQL注入.跨站脚本攻击.参数篡改.应用平台漏洞攻击.拒绝服务攻击等越来越多,传统的防 ...

  9. 十大排序算法JavaScript实现总结

    花费了几周的时间断断续续的练习和模仿与使用JavaScript代码实现了十大排序算法. 里面有每种算法的动图和静态图片演示,看到图片可以自己先按照图片的思路实现一下. github中正文链接,点击查看 ...

随机推荐

  1. Ext.net 3.1学习

    主页面前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MainF ...

  2. Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)

    本文中出现的,内核线程,轻量级进程,用户进程,用户线程等概念,如果不太熟悉, 可以参见 内核线程.轻量级进程.用户线程三种线程概念解惑(线程≠轻量级进程) Linux进程类别 虽然我们在区分Linux ...

  3. SQL中的每一张表都必须设有主键吗

    问题描述: 公司的数据库表有时候会看到没有主键的,SQL中的每一张表都必须设有主键吗? 主键的作用: 1)保证实体的完整性: 2)加快数据库的操作速度: 3)在表中添加新记录时,数据库ACCESS会自 ...

  4. C语句详细(初学者)

    C程序的执行部分是由语句组成的.程序的功能也是由执行语句实现的. C语句分为以下六类: 1.表达式语句:表达式加上分号“:”组成.执行表达式语句就是计算表达式的值. 2.函数调用语句:函数名.实际参数 ...

  5. Kafka设计原理

    一.入门 1.简介 Apache Kafka是一个分布式消息发布订阅系统.它最初由LinkedIn公司基于独特的设计实现为一个分布式的提交日志系统( a distributed commit log) ...

  6. el-table复选框分页记忆

    el-table 结合 el-pagination 实现分页后默认是没有复选框记忆功能的,对于这样的需求,无奈又只能硬着头皮上,试了网上的一些方法,没奏效,便自己上了. 简单的用法如下: <te ...

  7. GUI练习3

    将阿里山的积分卡拉斯的发生的咖啡机啊圣考虑到发送到敬爱费卢卡斯加

  8. Cocos2d-x CCControlPotentiometer之圆形音量button及特效

    1. 圆形音量button 事实上作者的本意应该是叫做"电位计button".可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果: 好了,不多解释,本篇到此 ...

  9. Cocos2d-x 线程的使用及线程使用中遇到的问题

    .h文件: #if CC_PLATFORM_ANDROID == CC_TARGET_PLATFORM #include "pthread.h" #endif #if CC_PLA ...

  10. javascript中的for in循环和for in循环的使用陷阱

    javascript中的for循环和for...in循环还是有些区别的,比如定义一个数组,然后用for..in循环输出 var array=[1,2,3,4,5,6]; for(var s in ar ...