一、说明
本篇文章主要写Mongodb基本知识的剩余部分,在此前我已经比较系统的发布了有关Mongodb的一些基础知识并将它们放在统一专栏里,链接放在这里了http://t.csdnimg.cn/TDAWw欢迎大家查看。
二、Mongodb操作(续上篇)
1、Mongodb条件操作符
条件操作符可以分为以下几类:比较操作符、逻辑操作符、元素操作符、数组操作符、以及其他常用操作符 。
1.1比较操作符
比较操作符有:
操作符 | 描述 | 示例 |
---|---|---|
$eq | 等于 | { age: { $eq: 25 } } |
$ne | 不等于 | { age: { $ne: 25 } } |
$gt | 大于 | { age: { $gt: 25 } } |
$gte | 大于等于 | { age: { $gte: 25 } } |
$lt | 小于 | { age: { $lt: 25 } } |
$lte | 小于等于 | { age: { $lte: 25 } } |
$in | 在指定的数组中 | { age: { $in: [25, 30, 35] } } |
$nin | 不在指定的数组中 | { age: { $nin: [25, 30, 35] } } |
例:
查找年龄小于18 且城市为 "成都" 的文档:
db.myCollection.find({ $or: [ { age: { $lt: 18 } }, { city: "成都" } ] });
1.2逻辑操作符
逻辑操作符有:
操作符 | 描述 | 示例 |
---|---|---|
$and | 逻辑与,符合所有条件 | { $and: [ { age: { $gt: 25 } }, { city: "New York" } ] } |
$or | 逻辑或,符合任意条件 | { $or: [ { age: { $lt: 25 } }, { city: "New York" } ] } |
$not | 取反,不符合条件 | { age: { $not: { $gt: 25 } } } |
$nor | 逻辑与非,均不符合条件 | { $nor: [ { age: { $gt: 25 } }, { city: "New York" } ] } |
例:
查找年龄小于18 且城市为 "成都" 的文档:
db.myCollection.find({ $or: [ { age: { $lt: 18 } }, { city: "成都" } ] });
1.3元素操作符
元素操作符有:
操作符 | 描述 | 示例 |
---|---|---|
$exists | 字段是否存在 | { age: { $exists: true } } |
$type | 字段的 BSON 类型 | { age: { $type: "int" } } |
例:
查找包含 age 字段的文档:
db.myCollection.find({ age: { $exists: true } });
1.4数组操作符
数组操作符有:
操作符 | 描述 | 示例 |
---|---|---|
$all | 数组包含所有指定的元素 | { students: { $all: ["one", "blue"] } } |
$elemMatch | 数组中的元素匹配指定条件 | { results: { $elemMatch: { score: { $gt: 80, $lt: 85 } } } } |
$size | 数组的长度等于指定值 | { tags: { $size: 3 } } |
例:
查找数组 students 中包含 "one" 和 "six" 的文档:
db.myCollection.find({ students: { $all: ["one", "six"] } });
1.5其他常用操作符
还有一些其他操作符如下:
操作符 | 描述 | 示例 |
---|---|---|
$regex | 匹配正则表达式 | { name: { $regex: /^A/ } } |
$text | 进行文本搜索 | { $text: { $search: "coffee" } } |
$where | 使用 JavaScript 表达式进行条件过滤 | { $where: "this.age > 25" } |
例:
查找名字以 "A" 开头的文档:
db.myCollection.find({ name: { $regex: /^A/ } });
三、MongoDB $type 操作符
1、介绍
$type 操作符用于查询具有指定类型的字段的文档,它允许指定一个或多个类型,并返回匹配这些类型的文档。
语法:
db.collection.find({ field: { $type: <type> } })
- field:要检查类型的字段。
- type:指定的 BSON 类型,可以是类型的数字代码或类型名称的字符串。
2、BSON 类型
以下是常见的 BSON 类型及其对应的数字代码和字符串名称:
类型代码 | 类型名称 |
---|---|
1 | double |
2 | string |
3 | object |
4 | array |
5 | binData |
6 | undefined |
7 | objectId |
8 | bool |
9 | date |
10 | null |
11 | regex |
12 | dbPointer |
13 | javascript |
14 | symbol |
15 | javascriptWithScope |
16 | int |
17 | timestamp |
18 | long |
19 | decimal |
255 | minKey |
127 | maxKey |
3、举例
查找字段类型为字符串的文档:
db.myCollection.find({ fieldName: { $type: "string" } })
或使用类型代码:
db.myCollection.find({ Number: { $type: 4 } })
查找 details 字段类型为对象,并且 score 字段类型为双精度浮点数的文档:
db.myCollection.find({
$and: [
{ details: { $type: "object" } },
{ score: { $type: "double" } }
]
})
四、MongoDB Limit 与 Skip 方法
如果你需要在 MongoDB 中读取指定数量的数据记录,可以使用 MongoDB 的 limit() 方法,如果想跳过指定数量的文档读取数据可以使用 skip() 方法。
limit() 方法用于限制查询结果返回的文档数量,而 skip() 方法用于跳过指定数量的文档。这两个方法通常一起使用,可以用来实现分页查询或在大型数据集上进行分批处理。
1、limit() 方法
limit() 方法用于限制查询结果返回的文档数量。
limit() 方法基本语法如下所示:
db.collection.find().limit(<limit>)
<limit>
:返回的文档数量。
例子:
(1)
// 返回前 10 个文档
db.myCollection.find().limit(10);
(2)
> db.col.find({},{"title":1,_id:0}).limit(2)
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
>
表示显示col集合中的title字段,不显示id字段
2、skip() 方法
skip() 方法用于跳过指定数量的文档,从而实现分页或分批查询。
skip() 方法语法格式如下:
db.collection.find().skip(<skip>)
<skip>
:要跳过的文档数量。
例子:
(1)
// 跳过前 10 个文档,返回接下来的 10 个文档
db.myCollection.find().skip(10).limit(10);
(2)以下实例只会显示第二条文档数据
>db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
{ "title" : "zzs" }
>
3、分页查询:
// 第一页,每页 10 个文档
db.myCollection.find().skip(0).limit(10);
// 第二页,每页 10 个文档
db.myCollection.find().skip(10).limit(10);
// 第三页,每页 10 个文档
db.myCollection.find().skip(20).limit(10);
注:skip()方法默认参数为 0 。
五、Mongodb 排序 (sort() 方法)
在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
sort()方法基本语法如下所示:
db.collection.find().sort({ field1: 1, field2: -1 })
{ field1: 1, field2: -1 }
:指定要排序的字段及排序顺序。1 表示升序,-1 表示降序。
例子:
按字段升序排序:
// 按 age 字段升序排序
db.myCollection.find().sort({ age: 1 });
按字段降序排序:
// 按 createdAt 字段降序排序
db.myCollection.find().sort({ createdAt: -1 });
可以指定多个字段进行排序,MongoDB 将按照指定的字段顺序依次排序。
// 先按 age 字段升序排序,再按 createdAt 字段降序排序
db.myCollection.find().sort({ age: 1, createdAt: -1 });
六、MongoDB 索引
1、介绍
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
在 MongoDB 中,常见的索引类型包括:
- 单字段索引:基于单个字段的索引。
- 复合索引:基于多个字段组合的索引。
- 文本索引:用于支持全文搜索。
- 地理空间索引:用于地理空间数据的查询。
- 哈希索引:用于对字段值进行哈希处理的索引。
2、创建索引
MongoDB 使用 createIndex() 方法来创建索引。
createIndex() 方法基本语法格式如下所示:
db.collection.createIndex( keys, options )
db
:数据库的引用。collection
:集合的名称。keys
:一个对象,指定了字段名和索引的排序方向(1 表示升序,-1 表示降序)。options
:一个可选参数,可以包含索引的额外选项。
options 参数是一个对象,可以包含多种配置选项,以下是一些常用的选项:
unique
:如果设置为true
,则创建唯一索引,确保索引字段的值在集合中是唯一的。background
:如果设置为true
,则索引创建过程在后台运行,不影响其他数据库操作。name
:指定索引的名称,如果不指定,MongoDB 会根据索引的字段自动生成一个名称。sparse
:如果设置为true
,创建稀疏索引,只索引那些包含索引字段的文档。expireAfterSeconds
:设置索引字段的过期时间,MongoDB 将自动删除过期的文档。v
:索引版本,通常不需要手动设置。weights
:为文本索引指定权重。
例子:
// 创建唯一索引
db.collection.createIndex( { field: 1 }, { unique: true } )
// 创建后台运行的索引
db.collection.createIndex( { field: 1 }, { background: true } )
// 创建稀疏索引
db.collection.createIndex( { field: 1 }, { sparse: true } )
// 创建文本索引并指定权重
db.collection.createIndex( { field: "text" }, { weights: { field: 10 } } )
创建地理空间索引
对于存储地理位置数据的字段,可以使用 2dsphere 或 2d 索引类型来创建地理空间索引。
// 2dsphere 索引,适用于球形地理数据
db.collection.createIndex( { location: "2dsphere" } )
// 2d 索引,适用于平面地理数据
db.collection.createIndex( { location: "2d" } )
3、创建哈希索引
使用哈希索引对字段进行哈希,以支持大范围的数值查找。
db.collection.createIndex( { field: "hashed" } )
4、 查看索引
使用 getIndexes() 方法可以查看集合中的所有索引:
db.collection.getIndexes()
5、删除索引
使用 dropIndex() 或 dropIndexes() 方法可以删除索引:
例子:
// 删除指定的索引
db.collection.dropIndex( "indexName" )
// 删除所有索引
db.collection.dropIndexes()
6、注意事项
(1)索引虽然可以提高查询性能,但也会增加写操作的开销。因此,在创建索引时需要权衡查询性能和写入性能。
(2)索引会占用额外的存储空间,特别是对于大型数据集,需要考虑索引的存储成本。
通过合理地设计和使用索引,可以大大提高 MongoDB 数据库的查询性能和响应速度,从而更好地支持应用程序的需求。
七、MongoDB 聚合
1、aggregate() 方法
aggregate() 方法的基本语法格式如下所示:
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
集合中的数据如下:
{
_id: ObjectId(7df78ad8902c)
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: ObjectId(7df78ad8902d)
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
_id: ObjectId(7df78ad8902e)
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
},
现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
"result" : [
{
"_id" : "runoob.com",
"num_tutorial" : 2
},
{
"_id" : "Neo4j",
"num_tutorial" : 1
}
],
"ok" : 1
}
>
解析这段代码就是
$group阶段:
_id: "$by_user"
: 这部分告诉MongoDB我们要按照by_user
字段的值来分组。这意味着所有具有相同作者的文章将会被归为一组。num_tutorial: {$sum: 1}
: 对于每个分组(即每个作者),$sum
操作符会累加一个计数值,这里的1代表每遇到一篇文档就计数一次,从而统计出每个作者的文章总数。
部分聚合的表达式:
表达式 | 描述 | 实例 |
---|---|---|
$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"}}}]) |
2、管道的概念
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
聚合框架中常用的几个操作:
- $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- $limit:用来限制MongoDB聚合管道返回的文档数。
- $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- $group:将集合中的文档分组,可用于统计结果。
- $sort:将输入文档排序后输出。
- $geoNear:输出接近某一地理位置的有序文档。
例子(.$match)
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。