您现在的位置是:首页 >学无止境 >MongoDB 基本介绍和操作网站首页学无止境
MongoDB 基本介绍和操作
目录
1、mongodb 简介
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。
MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
2、mongodb 概念解析
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | - | 表连接,MongoDB不支持 |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
数据库
一个mongodb中可以建立多个数据库。
MongoDB的默认数据库为"db",该数据库存储在data目录中。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,
不同的数据库也放置在不同的文件中。
文档
文档是一个键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,
并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,
也是 MongoDB 非常突出的特点。
3、mongodb 连接
使用用户名和密码连接到MongoDB服务器,你必须使用 'username:password@hostname/dbname' 格式,'username'为用户名,'password' 为密码。
例如:
使用用户名fred,密码foobar登录localhost的admin数据库。
mongodb://fred:foobar@localhost
连接 replica pair, 服务器1为example1.com服务器2为example2。
mongodb://example1.com:27017,example2.com:27017
4、mongodb 数据库操作
MongoDB 创建数据库的语法格式如下:
use DATABASE_NAME
如果数据库不存在,则创建数据库,否则切换到指定数据库。
查看所有数据库,可以使用 show dbs 命令。
MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。
MongoDB 删除数据库的语法格式如下:
db.dropDatabase()
删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。
MongoDB删除集合 语法格式如下:
db.collection.drop()
5、mongodb 文档操作
db.COLLECTION_NAME.insert(document)
实例:
db.col.insert(
{title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: 'test',
url: 'https://www.baidu.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
}
)
查看插入的文档
db.col.find()
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc...)等,
也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,
是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,
就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
参数说明:
document : 文档数据。
writeConcern :可选,抛出异常的级别。
实例:
>db.col.save({
"_id" : ObjectId("56064f89ade2f21f36b03136"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Runoob",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"NoSQL"
],
"likes" : 110
})
db.collection.remove(
<query>,
<justOne>
)
参数说明:
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档。
writeConcern :(可选)抛出异常的级别。
实例:
db.col.remove({'title':'MongoDB 教程'})
WriteResult({ "nRemoved" : 2 }) # 删除了两条数据
db.col.find() …… # 没有数据
db.COLLECTION_NAME.find()
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.col.find().pretty()
MongoDB 与 RDBMS Where 语句比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value>} | db.col.find({"by":"菜鸟教程"}).pretty() | where by = 'test' |
小于 | {<key>:{$lt:<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key>:{$lte:<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt:<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key>:{$gte:<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
6、mongodb 条件操作符
MongoDB中条件操作符有:
(>) 大于 - $gt (<) 小于 - $lt
(>=) 大于等于 - $gte (<= ) 小于等于 - $lte
AND 和 OR 联合使用
类似常规 SQL 语句为: 'where likes>50 AND (by = '菜鸟教程' OR title = 'MongoDB 教程')'
db.col.find({"likes": {$gt:50}, $or: [{"by": "test"},{"title": "MongoDB 教程"}]}).pretty()
{
"_id" : ObjectId("ksdfj11283012381023"),
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "test",
"url" : "https://www.baidu.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}
7、mongodb Limit与Skip 方法
limit()方法基本语法如下所示:
db.COLLECTION_NAME.find().limit(NUMBER)
实例:
db.col.find({},{"title":1,_id:0}).limit(2)
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
skip() 方法脚本语法格式如下:
>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
实例:
db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
{ "title" : "Java 教程" }
8、mongodb 排序
MongoDB sort()方法
在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的
字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。
语法
sort()方法基本语法如下所示:
db.COLLECTION_NAME.find().sort({KEY:1})
9、mongodb 索引
MongoDB使用 ensureIndex() 方法来创建索引。
语法
ensureIndex()方法基本语法格式如下所示:
db.COLLECTION_NAME.ensureIndex({KEY:1})
实例:
ensureIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。
db.col.ensureIndex({"title":1,"description":-1})
ensureIndex() 接收可选参数,可选参数列表如下:
参数 | 类型 | 描述 |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
10、mongodb 聚合
aggregate() 方法的基本语法格式如下所示:
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 将值加入一个数组中,不会判断是否有重复的值。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
管道的概念
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。
管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,
不能处理其它的文档。
这里我们介绍一下聚合框架中常用的几个操作:
$project:修改输入文档的结构。可以用来重命名、增加或删除域,
也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。
11、mongodb 复制(副本集)
mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是
从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据
副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB复制结构图如下所示:
MongoDB副本集设置
1、关闭正在运行的MongoDB服务器。
现在我们通过指定 --replSet 选项来启动mongoDB。--replSet 基本语法格式如下:
mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet
"REPLICA_SET_INSTANCE_NAME"
实例
mongod --port 27017 --dbpath "D:set upmongodbdata" --replSet rs0
以上实例会启动一个名为rs0的MongoDB实例,其端口号为27017。
副本集添加成员
rs.add(HOST_NAME:PORT)
实例:
rs.add("mongod1.net:27017")
12、mongodb 分片
在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的
读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理
更多的数据。
为什么使用分片
(1)复制所有的写入操作到主节点
(2)延迟的敏感数据会在主节点查询
(3)单个副本集限制在12个节点
(4)当请求量巨大时会出现内存不足。
(5)本地磁盘不足
(6)垂直扩展价格昂贵
上图中主要有如下所述三个主要组件:
Shard:
用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个
relica set 承担,防止主机单点故障
Config Server:
mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。
Query Routers:
前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
分片实例
分片结构端口分布如下:
Shard Server 1:27020
Shard Server 2:27021
Config Server :27100
Route Process:40000
步骤一:启动Shard Server
[root@100 /]# mkdir -p /www/mongoDB/shard/s0
[root@100 /]# mkdir -p /www/mongoDB/shard/s1
[root@100 /]# mkdir -p /www/mongoDB/shard/log
[root@100 /]# /usr/local/mongoDB/bin/mongod --port 27020 --dbpath=
/www/mongoDB/shard/s0 --logpath=/www/mongoDB/shard/log/s0.log
--logappend --fork
步骤二: 启动Config Server
[root@100 /]# mkdir -p /www/mongoDB/shard/config
[root@100 /]# /usr/local/mongoDB/bin/mongod --port 27100 --dbpath=
/www/mongoDB/shard/config --logpath=/www/mongoDB/shard/log/config.log
--logappend --fork
步骤三: 启动Route Process
/usr/local/mongoDB/bin/mongos --port 40000 --configdb localhost:27100 --fork
--logpath=/www/mongoDB/shard/log/route.log --chunkSize 500
步骤四: 配置Sharding
接下来,我们使用MongoDB Shell登录到mongos,添加Shard节点
[root@100 shard]# /usr/local/mongoDB/bin/mongo admin --port 40000
MongoDB shell version: 2.0.7
connecting to: 127.0.0.1:40000/admin
mongos> db.runCommand({ addshard:"localhost:27020" })
{ "shardAdded" : "shard0000", "ok" : 1 }
......
mongos> db.runCommand({ addshard:"localhost:27029" })
{ "shardAdded" : "shard0009", "ok" : 1 }
mongos> db.runCommand({ enablesharding:"test" }) #设置分片存储的数据库
{ "ok" : 1 }
mongos> db.runCommand({ shardcollection: "test.log", key: { id:1,time:1}})
{ "collectionsharded" : "test.log", "ok" : 1 }
步骤五: 程序代码内无需太大更改,直接按照连接普通的mongo数据库那样,
将数据库连接接入接口40000
13、mongodb 备份与恢复
mongodump命令脚本语法如下:
>mongodump -h dbhost -d dbname -o dbdirectory
-h:
MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:
需要备份的数据库实例,例如:test
-o:
备份的数据存放位置,例如:c:datadump,当然该目录需要提前建立,在备份完成后,
系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
mongodump 命令可选参数列表如下所示:
语法 | 描述 | 实例 |
---|---|---|
mongodump --host HOST_NAME --port PORT_NUMBER | 该命令将备份所有MongoDB数据 | mongodump --host runoob.com --port 27017 |
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY | mongodump --dbpath /data/db/ --out /data/backup/ | |
mongodump --collection COLLECTION --db DB_NAME | 该命令将备份指定数据库的集合。 | mongodump --collection mycol --db test |
MongoDB数据恢复
mongodb使用 mongorerstore 命令来恢复备份的数据。
语法
mongorestore命令脚本语法如下:
>mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
-h:
MongoDB所在服务器地址
-d:
需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
--directoryperdb:
备份数据所在位置,例如:c:datadump est,这里为什么要多加一个test,
而不是备份时候的dump,读者自己查看提示吧!
--drop:
恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,
备份后添加修改的数据都会被删除,慎用哦!
14、mongodb 监控
它会间隔固定时间 获取mongodb的当前运行状态,并输出
启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat
命令,如下所示:
D:set upmongodbin>mongostat
mongotop命令
用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在 读取和写入数据。
mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。
如下所示:
D:set upmongodbin>mongotop
15、mongodb 查询分析
使用 explain()
explain 操作提供了查询信息,使用索引及查询统计等。有利于我们对索引的优化。
接下来我们在 users 集合中创建 gender 和 user_name 的索引:
db.users.ensureIndex({gender:1,user_name:1})
db.users.find({gender:"M"},{user_name:1,_id:0}).explain()
查看返回结果集的字段:
indexOnly: 字段为 true ,表示我们使用了索引。
cursor:因为这个查询使用了索引,MongoDB中索引存储在B树结构中,所以这是也使用了
BtreeCursor类型的游标。如果没有使用索引,游标的类型是BasicCursor。这个键
还会给出你所使用的索引的名称,你通过这个名称可以查看当前数据库下的
system.indexes集合(系统自动创建,由于存储索引信息,这个稍微会提到)来得到
索引的详细信息。
n:当前查询返回的文档数量。
nscanned/nscannedObjects:表明当前这次查询一共扫描了集合中多少个文档,我们的目的是让这个数值和返回文档的数量越接近越好。
millis:当前查询所需时间,毫秒数。
indexBounds:当前查询具体使用的索引。
使用 hint()
虽然MongoDB查询优化器一般工作的很不错,但是也可以使用hints来强迫MongoDB使用
一个指定的索引。
这种方法某些情形下会提升性能。 一个有索引的collection并且执行一个多字段的查询
(一些字段已经索引了)。
如下查询实例指定了使用 gender 和 user_name 索引字段来查询:
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})
可以使用 explain() 函数来分析以上查询:
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()
16、mongodb 原子操作
询到的文档没有保存完整的情况。
比如文档的保存,修改,删除等,都是原子操作。
$set
用来指定一个键并更新键值,若键不存在并创建。
{ $set : { field : value } }
$unset
用来删除一个键。
{ $unset : { field : 1} }
$inc
$inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
{ $inc : { field : value } }
$push用法:
{ $push : { field : value } }
$pushAll
同$push,只是一次可以追加多个值到一个数组字段内。
{ $pushAll : { field : value_array } }
$pull
从数组field内删除一个等于value值。
{ $pull : { field : _value } }
增加一个值到数组内,而且只有当这个值不在数组内才增加。
$pop
删除数组的第一个或最后一个元素
{ $pop : { field : 1 } }
$rename
修改字段名称
{ $rename : { old_field_name : new_field_name } }
$bit
位操作,integer类型
{$bit : { field : {and : 5}}}
偏移操作符
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" :
[ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
> t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" :
[ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
17、mongodb ObjecctId
ObjectId 是一个12字节 BSON 类型数据,有以下格式:
(1)前4个字节表示时间戳
(2)接下来的3个字节是机器标识码
(3)紧接的两个字节由进程id组成(PID)
(4)最后三个字节是随机数。
创建新的ObjectId
使用以下代码生成新的ObjectId:
newObjectId = ObjectId()
上面的语句返回以下唯一生成的id:
ObjectId("5349b4ddd2781d08c09890f3")
创建文档的时间戳
由于 ObjectId 中存储了 4 个字节的时间戳,所以你不需要为你的文档保存时间戳字段,
你可以通过 getTimestamp 函数来获取文档的创建时间:
ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()
ObjectId 转换为字符串
在某些情况下,您可能需要将ObjectId转换为字符串格式。你可以使用下面的代码:
new ObjectId().str
以上代码将返回Guid格式的字符串: 5349b4ddd2781d08c09890f3
18、MongoDB Map Reduce
Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,
然后再将结果合并成最终结果(REDUCE)。
MongoDB提供的Map-Reduce非常灵活,对于大规模数据分析也相当实用。
以下是MapReduce的基本语法:
>db.collection.mapReduce(
function() {emit(key,value);}, //map 函数
function(key,values) {return reduceFunction}, //reduce 函数
{
out: collection,
query: document,
sort: document,
limit: number
}
)
map :映射函数 (生成键值对序列,作为 reduce 函数参数)。
reduce 统计函数,reduce函数的任务就是将key-values变成key-value,也就是把values数组
变成一个单一的值value。。
out 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
query 一个筛选条件,只有满足条件的文档才会调用map函数。
(query。limit,sort可以随意组合)
sort 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制
limit 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)
计算每个用户的文章数:
>db.posts.mapReduce(
function() { emit(this.user_name,1); },
function(key, values) {return Array.sum(values)},
{
query:{status:"active"},
out:"post_total"
}
)
以上 mapReduce 输出结果为:
{
"result" : "post_total",
"timeMillis" : 23,
"counts" : {
"input" : 5,
"emit" : 5,
"reduce" : 1,
"output" : 2
},
"ok" : 1
}
结果表明,共有4个符合查询条件(status:"active")的文档, 在map函数中生成了4个键值对
文档,最后使用reduce函数将相同的键值分为两组。
具体参数说明:
result:储存结果的collection的名字,这是个临时集合,MapReduce的连接关闭后自动就被删除了。
timeMillis:执行花费的时间,毫秒为单位
input:满足条件被发送到map函数的文档个数
emit:在map函数中emit被调用的次数,也就是所有集合中的数据总量
ouput:结果集合中的文档个数(count对调试非常有帮助)
ok:是否成功,成功为1
err:如果失败,这里可以有失败原因,不过从经验上来看,原因比较模糊,作用不大
19、mongodb 正则表达式
MongoDB 使用 $regex 操作符来设置匹配字符串的正则表达式。
以下命令使用正则表达式查找包含 w3cschool.cc 字符串的文章:
db.posts.find({post_text:{$regex:"w3cschool.cc"}})
以上查询也可以写为:
>db.posts.find({post_text:/w3cschool.cc/})
不区分大小写的正则表达式 ,我们可以设置 $options 为 $i。
db.posts.find({post_text:{$regex:"w3cschool.cc",$options:"$i"}})
{
"_id" : ObjectId("53493d37d852429c10000004"),
"post_text" : "hey! this is my post on W3Cschool.cc",
"tags" : [ "tutorialspoint" ]
}
数组元素使用正则表达式
如果你需要查找包含以 tutorial 开头的标签数据(tutorial 或 tutorials 或 tutorialpoint 或
tutorialphp), 你可以使用以下代码:
>db.posts.find({tags:{$regex:"tutorial"}})
优化正则表达式查询
如果你的文档中字段设置了索引,那么使用索引相比于正则表达式匹配查找所有的数据查
询速度更快。
如果正则表达式是前缀表达式,所有匹配的数据将以指定的前缀字符串为开始。
例如: 如果正则表达式为 ^tut ,查询语句将查找以 tut 为开头的字符串。
这里面使用正则表达式有两点需要注意:
正则表达式中使用变量。一定要使用eval将组合的字符串进行转换,不能直接将字符串拼接
后传入给表达式。否则没有报错信息,只是结果为空!实例如下:
var name=eval("/" + 变量值key +"/i");
以下是模糊查询包含title关键词, 且不区分大小写:
title:eval("/"+title+"/i") // 等同于 title:{$regex:title,$Option:"$i"}
20、MongoDB GridFS
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。
GridFS 可以更好的存储大于16M的文件。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为
MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据
(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
以下是简单的 fs.files 集合文档:
{
"filename": "test.txt",
"chunkSize": NumberInt(261120),
"uploadDate": ISODate("2014-04-13T11:32:33.557Z"),
"md5": "7b762939321e146569b07f72c62cca4f",
"length": NumberInt(646)
}
以下是简单的 fs.chunks 集合文档:
{
"files_id": ObjectId("534a75d19f54bfec8a2fe44b"),
"n": NumberInt(0),
"data": "Mongo Binary Data"
}
GridFS 添加文件
现在我们使用 GridFS 的 put 命令来存储 mp3 文件。 调用 MongoDB 安装目录下bin的 mongofiles.exe工具。
打开命令提示符,进入到MongoDB的安装目录的bin目录中,找到mongofiles.exe,并输入下面的代码:
>mongofiles.exe -d gridfs put song.mp3
GridFS 是存储文件的数据名称。如果不存在该数据库,MongoDB会自动创建。Song.mp3 是音频文件名。
使用以下命令来查看数据库中文件的文档:
>db.fs.files.find()
以上命令执行后返回以下文档数据:
{
_id: ObjectId('534a811bf8b4aa4d33fdf94d'),
filename: "song.mp3",
chunkSize: 261120,
uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41",
length: 10401959
}
我们可以看到 fs.chunks 集合中所有的区块,以下我们得到了文件的 _id 值,我们可以根据这个 _id 获取区块(chunk)的数据:
>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})
以上实例中,查询返回了 40 个文档的数据,意味着mp3文件被存储在40个区块中。