MongoDB 入门
MongoDB 入门
MongoDB是一个以文档为中心的NOSQL数据库,具备高性能、高可用性及可伸缩性等特性。
下面介绍MongoDB中的基础概念:
Database/数据库
与关系数据库类似,MongoDB中,数据库代表了一个独立的数据存储库,每个数据库在文件系统上都有自己的一组文件。一个MongoDB服务器通常有多个数据库。
Collection/集合
Collection/集合是一组MongoDB文档,相当于关系数据库中的表,包含于数据库中。与关系数据库的表不同,集合不要求固定一致的表结构,集合中的文档可以有不同的字段。但是,集合中的文档都应具有相似或相关联的意义,例如:订单集合,包含了全部订单文档。
Document/文档
文档是一组JSON格式的键值对,。文档具有动态数据结构,同一集合中的文档不需要具有相同的字段集。
下表显示了RDBMS术语与MongoDB之间的关系。
关系数据库 | MongoDB |
---|---|
Database | Database |
Table | Collection |
Tuple/Row | Document |
column | Field |
Table Join | Embedded Documents |
Primary Key | Primary Key (由mongodb本身提供的默认键_id) |
服务器和客户端 | |
Mysqld/Oracle | mongod |
mysql client | mongo |
文档示例
下面的示例,显示了一个站点的文档结构,是一组逗号分隔的键值对。
{
_id: ObjectId("507f191e810c19729de860ea")
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by: 'demo',
url: 'httpS://www.baidu.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100,
comments: [
{
user:'user1',
message: 'My first demo',
dateCreated: new Date(2021,7,30,15,15),
like: 0
},
{
user:'user2',
message: 'My second demo',
dateCreated: new Date(2021,7,30,17,45),
like: 5
}
]
}
_id是一个12字节的十六进制数字,唯一标识文档。你可以在插入文档时指定_id
,如果不指定,MongoDB将会生成一个。这12个字节由下面几部分组成:
- 4 字节 – 表示自Unix纪元以来的秒数
- 5 字节 – 随机值
- 3 字节 – 计数器,从一个随机值开始
MongoDB 优势
任何关系数据库都有一个典型的数据结构设计,表明了表结构及表之间的关系。而在MongoDB中,没有关系的概念。
MongoDB相对于RDBMS的优势
- 无固定结构 – MongoDB是一个文档数据库,一个集合中可以包含不同的文档。文档的字段数、内容和大小都可以不同。
- 单个对象的结构是清晰的。
- 没有复杂的表连接。
- 查询功能强大。MongoDB的查询功能几乎与SQL一样强大,使用基于文档的查询语言,可以对文档进行动态查询。
- 易于调优。
- 易于扩展。
- 应用程序对象与数据库对象天然对应。
- 使用内存存储工作集,可以更快地访问数据。
为什么使用MongoDB?
- 面向文档的数据库 – 数据以JSON格式的文档存储。
- 任意字段的索引
- 复制和高可用性
- 自动分片
- 丰富的查询
- 就地更新快
- MongoDB的专业支持
哪些场景使用MongoDB?
- 大数据
- 内容管理和交付
- 移动应用/社交应用
- 用户数据管理
- 数据中心
MongoDB 创建数据库
use 命令
MongoDB通过命令use 数据库名
创建数据库。如果数据库不存在,该命令将创建一个数据库,否则将返回已有数据库。
语法
use 数据库名
语句的基本语法如下:
use 数据库名
例子
如果想使用名为test
的数据库,可通过如下命令
> use test
switched to db test
要检查当前数据库,可使用db
命令:
> db
test
如果要列出全部数据库,可使用show dbs
命令:
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
您刚创建的数据库(mydb)不在列表中,空数据库不会显示,需要向其插入至少一个文档。
> db.site.insert({"name":"demo"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
MongoDB 删除数据库
dropDatabase() 方法
MongoDB db.dropDatabase()
命令用于删除数据库。
语法
dropDatabase()
命令的基本语法如下:
db.dropDatabase()
这将删除当前数据库。如果没有选择任何数据库,那么它将删除默认的“test”数据库。
例子
首先,使用命令show dbs
检查可用数据库列表。
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
如果想删除数据库test
,可通过如下操作:
> use testswitched to db test> db.dropDatabase(){ "dropped" : "test", "ok" : 1 }
现在检查数据库列表。
> show dbsadmin 0.000GBconfig 0.000GBlocal 0.000GB
MongoDB 创建集合
createCollection() 方法
MongoDB中的db.createCollection(name, options)
方法用于创建集合。
语法
createCollection()
命令的基本语法如下:
db.createCollection(name, options)
命令中,name
是要创建的集合名称,options
是一个文档,用于指定集合的配置。
参数 | 类型 | 描述 |
---|---|---|
Name | String | 要创建的集合名称 |
Options | Document | (可选)指定内存大小、索引等选项/td> |
options
参数是可选的,下面是可以使用的选项列表:
字段 | 类型 | 描述 |
---|---|---|
capped | Boolean | (可选)如果为真,则启用有上限的集合。封顶集合是一个固定大小的集合,当它达到最大大小时自动覆盖其最老的条目。 如果指定为真,还需要指定size参数。 |
size | number | (可选)为有上限的集合指定最大字节大小。如果capped为真,那么还需要指定该字段。 |
max | number | (可选)指定上限集合中允许的最大文档数量。 |
在插入文档时,MongoDB首先检查封顶集合的size
字段,然后检查max
字段。
例子
没有选项的createCollection()
方法例子如下:
> use testswitched to db test> db.createCollection("mycollection"){ "ok" : 1 }
可以使用show collections
命令检查当前数据库中的集合。
> show collectionsmycollectiontest
下面是createCollection()
方法使用选项的例子
> db.createCollection("mycollection3", { capped : true, size : 6142800, max : 10000 } ){ "ok" : 1 }
MongoDB中,不需要创建集合,当插入文档时,MongoDB自动创建集合。
> db.test1.insert({"post": "mongodb"})WriteResult({ "nInserted" : 1 })> show collectionsmycollectionmycollection1testtest1
MongoDB 删除集合
drop() 方法
drop()
方法用于从数据库中删除集合。
语法
drop()
命令的基本语法如下
db.COLLECTION_NAME.drop()
例子
首先显示数据库test
中的所有集合。
> use testswitched to db test> show collectionsmycollectionmycollection1testtest1
现在删除名为mycollection2的集合。
> db.mycollection1.drop()true
再次将集合列表检查到数据库中。
> show collectionsmycollectiontesttest1
如果集合被成功删除,drop()
方法将返回true,否则返回false。
MongoDB 数据类型
MongoDB支持许多数据类型。常用的一些是
- String − 字符串是最常用的数据类型,MongoDB中的字符串必须是UTF-8编码。
- Integer − 整数类型用于存储数值。整数可以是32位,也可以是64位,这取决于你的服务器。
- Boolean − 布尔类型用于存储布尔值(true/ false)。
- Double − 双精度类型用于存储浮点值。
- Min/ Max keys − 此类型用于将值与最低和最高的BSON元素进行比较。
- Arrays − 此类型用于将数组、列表或多个值存储到一个键中。
- Timestamp − ctimestamp。时间戳,用于记录文档何时被修改或创建。
- Object − 这种数据类型用于嵌入文档。
- Null − 此类型用于存储Null值。
- Symbol − 此数据类型与字符串用法相同; 然而,它通常用于某些使用特定符号的语言。
- Date − 此数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建date对象,并将日、月、年传入其中,来指定自己的日期时间。
- Object ID − 此数据类型用于存储文档的ID。
- Binary data − 这种数据类型用于存储二进制数据。
- Code − 此数据类型用于将JavaScript代码存储到文档中。
- Regular expression − 此数据类型用于存储正则表达式。
MongoDB 插入文档
insert() 方法
要将数据插入MongoDB集合,需要使用insert()
或save()
方法。
语法
insert()
命令的基本语法如下
>db.COLLECTION_NAME.insert(document)
例子
>db.test1.insert({ title: 'MongoDB 入门', description: 'MongoDB是开源的NoSQL数据库', by: 'test', url: 'https://www.baidu.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100})
这里test1
是我们的集合名称,在前面创建过。如果集合不存在,那么MongoDB将创建这个集合,然后将文档插入其中。
在插入的文档中,如果没有指定_id
参数,则MongoDB为该文档分配一个唯一的ObjectId。
_id
是一个集合中,每个文档唯一标识,_id
是12个字节的16进制数字。12字节划分如下
- 4 字节 – 表示自Unix纪元以来的秒数
- 5 字节 – 随机值
- 3 字节 – 计数器,从一个随机值开始
要在一次查询中插入多个文档,可以在insert()
命令中,传递一个文档数组。
例子
> db.test1.insert([ { title: 'MongoDB 入门', description: 'MongoDB是一个以文档为中心的NOSQL数据库', by: 'test', url: 'https://www.baidu.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 88 }, { title: 'MongoDB 优势', description: "MongoDB相对于RDBMS的优势", by: 'test', url: 'https://www.baidu.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 89, comments: [ { user:'user1', message: 'My first comment', dateCreated: new Date(2021,6,31,2,35), like: 0 } ] }])
要插入文档,还可以使用db.post.save(document)
方法。如果没指定_id
,那么save()
方法将与insert()
方法一样,自动生成_id
。如果指定_id
,则它将替换_id
所标识文档的整个数据。
MongoDB 查询文档
find() 方法
要从MongoDB集合查询数据,需要使用find()
方法。
语法
find()
方法的基本语法如下
db.COLLECTION_NAME.find()
方法显示文档时,是没有结构化的。
pretty() 方法
要以格式化的方式显示结果,可以使用pretty()
方法。
语法
db.mycollection.find().pretty()
例子
> db.test1.find().pretty(){ "_id" : ObjectId("6103b4425c56b69ebcf036c7"), "title" : "MongoDB 概述", "description" : "MongoDB是一个以文档为中心的NOSQL数据库", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 88}
除了find()
方法之外,还有findOne()
方法,它只返回一个结果。
> db.test1.findOne(){ "_id" : ObjectId("6103b4425c56b69ebcf036c7"), "title" : "MongoDB 概述", "description" : "MongoDB是一个以文档为中心的NOSQL数据库", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 88}
MongoDB查询条件与SQL Where对比
find()
方法可以传入查询条件,为便于理解,下表列出了等价的SQL Where语句。
操作 | 语法 | 例子 | 等价于 |
---|---|---|---|
等于 | { |
db.mycol.find({“by”:”qikegu.com”}).pretty() | where by = ‘qikegu.com’ |
小于 | { |
where likes < 50 | |
小于等于 | { |
where likes <= 50 | |
大于 | { |
where likes > 50 | |
大于等于 | { |
where likes >= 50 | |
不等于 | { |
where likes != 50 |
AND
语法
在find()
方法中,查询条件可以使用AND
,下面是AND
的基本语法
> db.test1.find( { $and: [ {key1: value1}, {key2:value2} ] }).pretty()
$and
也可以省略,直接传入键值对,以逗号分隔,格式如下:
> db.test.find( { key1: value1, key2:value2 }).pretty()
例子
下面的例子将显示由’test’编写并且标题是’MongoDB 概述’的所有教程’。
> db.test1.find({$and:[{"by": "test"},{"title": "MongoDB 概述"}]}).pretty() { "_id" : ObjectId("6103b4425c56b69ebcf036c7"), "title" : "MongoDB 概述", "description" : "MongoDB是一个以文档为中心的NOSQL数据库", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 88 }
对于上面的示例,等效where子句是where by = 'test'和' title = 'MongoDB 概述'
。可以在find
子句中传递任意数量的键值对。
OR
语法
在find()
方法中,查询条件可以使用OR
,下面是OR
的基本语法
> db.test1.find( { $or: [ {key1: value1}, {key2:value2} ] }).pretty()
例子
下面的例子将显示由“test”编写或标题为“MongoDB 概述”的教程。
> db.test1.find({$or:[{"by": "test"},{"title": "MongoDB 概述"}]}).pretty(){ "_id" : ObjectId("6103b4425c56b69ebcf036c7"), "title" : "MongoDB 概述", "description" : "MongoDB是一个以文档为中心的NOSQL数据库", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 88}{ "_id" : ObjectId("6103b4425c56b69ebcf036c8"), "title" : "MongoDB 优势", "description" : "MongoDB相对于RDBMS的优势", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 89, "comments" : [ { "user" : "user1", "message" : "My first comment", "dateCreated" : ISODate("2021-07-30T18:35:00Z"), "like" : 0 } ]}
AND, OR 一起使用
例子
下面的示例将显示符合以下条件的文档:获赞数大于88,并且要么标题是“MongoDB 概述”,要么由”test”编写。等效SQL where子句是where like >88 AND (by = 'test'或title = 'MongoDB 概述')
> db.test1.find({"likes": {$gt:88}, $or: [{"by": "test"}, {"title": "MongoDB 概述"}]}).pretty() { "_id" : ObjectId("6103b4425c56b69ebcf036c8"), "title" : "MongoDB 优势", "description" : "MongoDB相对于RDBMS的优势", "by" : "test", "url" : "https://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 89, "comments" : [ { "user" : "user1", "message" : "My first comment", "dateCreated" : ISODate("2021-07-30T18:35:00Z"), "like" : 0 } ] }
MongoDB 更新文档
MongoDB的update()
和save()
方法可用于更新文档。
MongoDB Update() 方法
update()
方法类似SQL UDPATE语句,可以根据条件更新现有文档。
语法
update()
方法的基本语法如下
db.COLLECTION_NAME.update(SELECTION_CRITERIA, UPDATED_DATA)
例子
假设test1集合有以下数据。
{ "_id" : ObjectId("6103b3935c56b69ebcf036c3"), "title" : "MongoDB 入门", }{ "_id" : ObjectId("6103b3935c56b69ebcf036c4"), "title" : "MongoDB 优势" }
下面的示例,修改标题为“MongoDB 优势”的文档,把它的标题修改为“MongoDB 优点”。
> db.test1.update({'title':'MongoDB 优势'}, {$set:{'title':'MongoDB 优点'}})WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
默认情况下,MongoDB只更新一个文档。要更新多个文档,需要将参数“multi”设置为true。
> db.test1.update({'title':'MongoDB 入门'}, {$set:{'title':'MongoDB 概述'}},{multi:true})WriteResult({ "nMatched" : 5, "nUpserted" : 0, "nModified" : 5 })
MongoDB Save() 方法
save()
方法根据文档参数更新现有文档或插入新文档。
语法
Save()
方法的基本语法如下
db.COLLECTION_NAME.save({_id:ObjectId(), NEW_DATA})
例子
下面的示例,把新内容保存到_id
为’6103b3935c56b69ebcf036c3’的文档中。
> db.test1.save( { "_id" : ObjectId("6103b3935c56b69ebcf036c3"), "title":"MongoDB 介绍", "by":"test" })WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
MongoDB 删除文档
remove() 方法
MongoDB的remove()
方法用于从集合中删除文档。方法接受两个参数:
- deletion criteria / 删除条件 – 符合条件的文档将被删除。
- justOne – 如果设置为true或1,则只删除一个文档。
语法
remove()
方法的基本语法如下
> db.COLLECTION_NAME.remove(DELLETION_CRITTERIA)
例子
假设test1集合有以下数据:
{ "_id" : ObjectId("5cf7b4839ad87fde6fd23a03"), "title" : "MongoDB 介绍" }{ "_id" : ObjectId("5cf7b51d9ad87fde6fd23a04"), "title" : "MongoDB 概述" }{ "_id" : ObjectId("5cf7b91d9ad87fde6fd23a07"), "title" : "MongoDB 优势" }
下面的示例,将删除标题为“MongoDB 概述”的所有文档。
db.test1.remove({'title':'MongoDB 概述'})
只删除1条
如果有多个记录,只想删除第一个记录,可以在remove()
方法中设置justOne
参数。
> db.COLLECTION_NAME.remove(DELETION_CRITERIA, 1)
删除全部
如果没有指定删除条件,那么将删除集合中的全部文档。这相当于SQL的truncate命令。
db.test1.remove()
MongoDB 条件操作符
描述
条件操作符用于比较两个表达式并从mongoDB集合中获取数据。
MongoDB中条件操作符有:
- (>) 大于 - $gt
- (<) 小于 - $lt
- (>=) 大于等于 - $gte
- (<= ) 小于等于 - $lte
我们使用的数据库名称为"test" 我们的集合名称为"test1",以下为我们插入的数据。
为了方便测试,我们可以先使用以下命令清空集合 "test1" 的数据:
> db.test1.remove({})WriteResult({ "nRemoved" : 1 })
插入以下数据
>db.test1.insert({ "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ 'php'], "likes" :200})
>db.test1.insert({ title: 'Java 学习', description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。', by: 'demo', url: 'http://www.baidu.com', tags: ['java'], likes: 150})
>db.test1.insert({title: 'MongoDB 学习', description: 'MongoDB 是一个 Nosql 数据库', by: 'demo', url: 'http://www.badiu.com', tags: ['mongodb'], likes: 100})
使用find()命令查看数据:
> db.test1.find(){ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 100 }{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB (>) 大于操作符 - $gt
如果你想获取 "test1" 集合中 "likes" 大于 100 的数据,你可以使用以下命令:
db.test1.find({likes : {$gt : 100}})
类似于SQL语句:
Select * from test1 where likes > 100;
输出结果:
> db.test1.find({likes : {$gt : 100}}){ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 200 }{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }
MongoDB(>=)大于等于操作符 - $gte
如果你想获取"test1"集合中 "likes" 大于等于 100 的数据,你可以使用以下命令:
db.test1.find({likes : {$gte : 100}})
类似于SQL语句:
Select * from test1 where likes >=100;
输出结果:
> db.test1.find({likes : {$gte : 100}}){ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 200 }{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB (<) 小于操作符 - $lt
如果你想获取"test1"集合中 "likes" 小于 150 的数据,你可以使用以下命令:
db.test1.find({likes : {$lt : 150}})
类似于SQL语句:
Select * from test1 where likes < 150;
输出结果:
> db.test1.find({likes : {$lt : 150}}){ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB (<=) 小于等于操作符 - $lte
如果你想获取"col"集合中 "likes" 小于等于 150 的数据,你可以使用以下命令:
db.test1.find({likes : {$lte : 150}})
类似于SQL语句:
Select * from test1 where likes <= 150;
输出结果:
> db.test1.find({likes : {$lte : 150}}){ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB 使用 (<) 和 (>) 查询 - $lt 和 $gt
如果你想获取"col"集合中 "likes" 大于100,小于 200 的数据,你可以使用以下命令:
db.test1.find({likes : {$lt :200, $gt : 100}})
类似于SQL语句:
Select * from test1 where likes>100 AND likes<200;
输出结果:
> db.test1.find({likes : {$lt :200, $gt : 100}}){ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }
MongoDB $type 操作符
$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB 中可以使用的类型如下表所示:
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1 . |
Max key | 127 |
使用find()命令查看数据:
> db.test1.find(){ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 100 }{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB 操作符 - $type 实例
如果想获取 "test1" 集合中 title 为 String 的数据,你可以使用以下命令:
db.test1.find({"title" : {$type : 2}})或db.test1.find({"title" : {$type : 'string'}})
输出结果为:
{ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 200 }{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150 }{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100 }
MongoDB Projection
MongoDB中,投影/projection用于选择字段。例如,一个文档有5个字段,而你只需要3个字段,那么就可以使用投影/Projection选择需要的字段。
find() 方法
在MongoDB 查询文档中解释过,find()
方法接受第二个可选参数,即要检索的字段列表。find()
方法默认将返回文档的所有字段,通过设置projection可以选择要返回的字段。投影/projection是一组字段列表,值设置为1的字段返回,值为0的字段隐藏。
语法
find()
方法中,投影/projection基本语法如下
> db.COLLECTION_NAME.find({}, {KEY:1})
例子
假设集合test1有以下数据
{ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036ca"), "title" : "Java学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036cb"), "title" : "MongoDB学习" }
下面的示例,在查询文档时,只显示文档标题。
> db.test1.find({}, {"_id":0, "title":1}){ "title" : "PHP学习" }{ "title" : "Java 学习" }{ "title" : "MongoDB 学习" }
注意,在执行
find()
方法时总是显示_id
字段,如果不需要该字段,则需要将其设置为0。
MongoDB Limit与Skip方法
limit() 方法
类似SQL Limit语句,MongoDB中,使用limit()
方法限制返回的结果数。
语法
limit()
方法的基本语法如下
db.COLLECTION_NAME.find().limit(NUMBER)
例子
假设集合test1有以下数据。
{ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036ca"), "title" : "Java学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036cb"), "title" : "MongoDB学习" }
下面的示例,在查询文档时只显示2个文档。
> db.test1.find({},{"title":1,_id:0}).limit(2){ "title" : "PHP学习" }{ "title" : "Java 学习" }
如果limit()
方法中没有指定数量参数,将显示集合中的所有文档。
MongoDB Skip() 方法
除了limit()
方法之外,还有一个方法skip()
也接受number类型参数,用于跳过文档的数量。可以看出,Skip()
方法的作用类似MySQL Offset语句。
语法
skip()
方法的基本语法如下
db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
例子
下面的示例,只显示第二个文档:
> db.test1.find({},{"title":1,_id:0}).limit(1).skip(1){ "title" : "Java 学习" }
注意,
skip()
方法的默认值是0。
MongoDB 排序
sort() 方法
要在MongoDB中对结果进行排序,可使用sort()
方法。该方法接受一个包含字段列表及其排序顺序的参数,要指定排序顺序,使用1和-1,1用于升序,-1用于降序。
语法
sort()
方法的基本语法如下
db.COLLECTION_NAME.find().sort({KEY:1})
例子
假设集合test1有以下数据。
{ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036ca"), "title" : "Java学习" }{ "_id" : ObjectId("6103ba645c56b69ebcf036cb"), "title" : "MongoDB学习" }
下面的示例,将显示按标题降序排序的文档。
> db.test1.find({},{"title":1, _id:0}).sort({"title":-1}){ "title" : "PHP学习" }{ "title" : "MongoDB 学习" }{ "title" : "Java 学习" }
注意,如果没有指定升序还是降序,那么
sort()
方法将按升序排列。
MongoDB 索引
索引可以让查询更快。如果没有索引,查询文档时时,MongoDB必须扫描集合的每个文档。这种扫描效率非常低,MongoDB需要处理大量数据。
索引针对特定字段或一组字段创建。
createIndex() 方法
要创建索引,可使用createIndex()
方法。
语法
createIndex()
方法的基本语法如下:
db.COLLECTION_NAME.createIndex({KEY:1})
这里的键是要创建索引的字段,1表示按升序创建索引,-1表示降序。
例子
db.test1.createIndex({"title":1})
在createIndex()
方法中,可以传递多个字段,该方法将在多个字段上创建索引。
db.test1.createIndex({"title":1,"description":-1})
createIndex()
方法还接受其他一些可选参数,如下所示:
参数 | 类型 | 描述 |
---|---|---|
Parameter | Type | Description |
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 | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
MongoDB 聚合
聚合操作对查询到的记录分组,然后对每组记录进行统计计算,返回统计结果。在SQL中,count(*)
配合group by
可以统计每组记录的条数,就相当于MongoDB中的聚合sum。
aggregate() 方法
MongoDB中,聚合操作可以使用aggregate()
方法。
语法
aggregate()
方法的基本语法如下:
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
例子
在test1集合中有以下数据:
> db.test1.find().pretty(){ "_id" : ObjectId("6103ba645c56b69ebcf036c9"), "title" : "PHP学习", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "php" ], "likes" : 200}{ "_id" : ObjectId("6103bb195c56b69ebcf036ca"), "title" : "Java 学习", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "demo", "url" : "http://www.baidu.com", "tags" : [ "java" ], "likes" : 150}{ "_id" : ObjectId("6103bb2c5c56b69ebcf036cb"), "title" : "MongoDB 学习", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "demo", "url" : "http://www.badiu.com", "tags" : [ "mongodb" ], "likes" : 100}
现在,要统计demo写了多少个教程,可以使用aggregate()
方法:
> db.test1.aggregate([{$group : {_id : "$by", num_tutorial : {$sum : 1}}}]){ "_id" : "test", "num_tutorial" : 2 }
上面的例子,等价的SQL查询是
select `by`, count(*) from test1 group by `by`
在上面的例子中,按照字段by
对结果进行分组,并统计分组中记录条数。下面是聚合表达式的列表:
表达式 | 描述 | 例子 |
---|---|---|
$sum | 汇总集合中文档的字段值。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, num_tutorial : {sum:“sum : “sum:“likes”}}}]) |
$avg | 计算集合中,所有文档中所有给定值的平均值。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, num_tutorial : {avg:“avg : “avg:“likes”}}}]) |
$min | 获取集合中,文档字段的最小值 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, num_tutorial : {min:“min : “min:“likes”}}}]) |
$max | 获取集合中,文档字段的最大值 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, num_tutorial : {max:“max : “max:“likes”}}}]) |
$push | 将全部文档的某个字段值作为数组插入到结果中。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, url : {push:“push: “push:“url”}}}]) |
$addToSet | 将全部文档的某个字段值作为数组插入到结果中,但字段值不重复。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, url : {addToSet:“addToSet : “addToSet:“url”}}}]) |
$first | 获取分组中的最后一个文档,通常,文档是有序的这个操作才有意义。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, first_url : {first:“first : “first:“url”}}}]) |
$last | 获取分组中的首个文档,通常,文档是有序的这个操作才有意义。 | db.test1.aggregate([{ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : “by”, last_url : {last:“last : “last:“url”}}}]) |
管道
在UNIX命令中,管道可以让某些命令的输出,作为另一个命令的输入,以此类推。MongoDB的聚合框架中也支持相同的概念,某些操作阶段输出一组文档,这些文档可以作为另一组操作阶段的输入,以此类推。
下面是聚合框架的可能阶段,可以把这些阶段串联组合起来:
-
$project — 用于从集合中选择某些字段。
-
$match — 这是一个过滤操作,过滤文档。
-
$group — 这是如上所述的实际聚合。
-
$sort — 对文档进行排序。
-
$skip – 结果偏移量,类似mysql中的offset。
-
$limit — 限定结果数量。
-
$unwind
– 用于展开使用数组的文档。例如:
{ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] }
复制
会被展开成为:
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }
MongoDB 备份数据
MongoDB数据转储
要在MongoDB中创建数据库备份,可以使用mongodump
命令。这个命令将把服务器的全部数据转储到文件目录中。
语法
mongodump命令的基本语法如下
# mongodump
例子
启动mongod服务器,假设服务器运行本地主机和端口27017上。命令行中,执行mongodump
[root@qikegu ~]# mongodump
该命令将连接到运行在本地主机和端口27017的服务器,并将服务器的所有数据备份到目录./dump/
。下面是命令的输出:
2021-07-10T13:12:04.913+0800 writing admin.system.version to2021-07-10T13:12:04.915+0800 done dumping admin.system.version (1 document)2021-07-10T13:12:04.915+0800 writing test.test to2021-07-10T13:12:04.915+0800 writing test.test1 to2021-07-10T13:12:04.915+0800 writing test.mycollection to2021-07-10T13:12:04.919+0800 done dumping mydb.test (0 documents)2021-07-10T13:12:04.924+0800 done dumping mydb.test1 (5 documents)2021-07-10T13:12:04.925+0800 done dumping mydb.mycollection (0 documents)
复制
下面是可以与mongodump命令一起使用的选项列表。
语法 | 描述 | 例子 |
---|---|---|
mongodump –host HOST_NAME –port PORT_NUMBER | 此命令将备份指定主机上,MongoDB服务器中的所有数据库。 | mongodump –host localhost –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 |
恢复数据
要恢复备份数据,使用mongorestore
命令。此命令从备份目录中还原所有数据。
语法
mongorestore命令的基本语法是
# mongorestore
下面是命令的输出:
[root@kali ~]# mongorestore
2021-07-10T13:22:23.355+0800 using default 'dump' directory
2021-07-10T13:22:23.356+0800 preparing collections to restore from
2021-07-10T13:22:23.357+0800 reading metadata for mydb.qikegu from dump/test/test1.metadata.json
2021-07-10T13:22:23.358+0800 restoring test.test1 from dump/test/test1.bson
2021-07-10T13:22:23.358+0800 reading metadata for test.mycollection from dump/test/test1.metadata.json
2021-07-10T13:22:23.358+0800 restoring mydb.test1 from dump/mydb/mycollection.bson
2021-07-10T13:22:23.358+0800 reading metadata for test.mycollection from dump/test/mycollection.metadata.json
2021-07-10T13:22:23.361+0800 restoring mydb.mycollection3 from dump/test/mycollection.bson
2021-07-10T13:22:23.363+0800 no indexes to restore
2021-07-10T13:22:23.364+0800 finished restoring test.test1 (0 documents)
2021-07-10T13:22:23.364+0800 no indexes to restore
2021-07-10T13:22:23.364+0800 finished restoring test.mycollection (0 documents)
2021-07-10T13:22:23.368+0800 error: multiple errors in bulk operation:
- E11000 duplicate key error collection: test.test1 index: _id_ dup key: { : ObjectId('6103ba645c56b69ebcf036c9') }
- E11000 duplicate key error collection: test.test1 index: _id_ dup key: { : ObjectId('6103ba645c56b69ebcf036ca') }
- E11000 duplicate key error collection: test.test1 index: _id_ dup key: { : ObjectId('6103ba645c56b69ebcf036cb') }
2021-07-10T13:22:23.368+0800 restoring indexes for collection test.test1 from metadata
2021-07-10T13:22:23.368+0800 finished restoring mydb.qikegu (5 documents)
2021-07-10T13:22:23.368+0800 done