2008 年左右,网站 、 论坛、社交网络
开始高速发展,传统的关系型数据库在存储及处理数据的时候受到了很大的挑战 ,其中主要体现在以下几点:
对数据联表的查询需求不是那么强烈 ,也并不需要在数据写入后立刻读取,但对数据的读取和并发写入速度有非常高的要求
。 在这样的情况下 ,非关系型数据库得到高速的发展 。NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。
MongoDB 就是这样一款非关系型的数据库,什么叫非关系型?就是把数据直接放进一个大仓库,不标号、不连线、单纯的堆起来。传统数据库由于受到各种关系的累赘,各种数据形式的束缚,难以处理海量数据以及超高并发的业务场景。
这类数据库主要是使用数据结构中的键 Key 来查找特定的数据Value。
优点:在存储时不采用任何模式,因此极易添加数据
这类数据库具有极高的读写性能,用于处理大量数据的高访问负载比较合适
。
键值对数据库适合大量数据的高访问及写入负载场景,例如日志系统
。主要代表是 Redis、Flare
。
这类数据库满足了海量数据的存储和访问需求
,同时对字段要求不严格,可以随意增加、删除、修改字段,且不需要预先定义表结构,所以适用于各种网络应用。
主要代表是 MongoDB、CouchDB
。
主要代表是Cassandra 、Hbase
。
这类数据库查找速度快,可扩展性强
,适合用作分布式文件存储系统。
主要代表是InfoGrid 、Neo4J
。
这类数据库利用“图结构”的相关算法来存储实体之间的关系信息
,适合用于构建社交网络和推荐系统的关系图谱。
NoSQL 并不能完全取代关系型数据库,NoSQL 主要被用来处理大量且多元数据的存储及运算问题
。在这样的特性差异下,我们该如何选择合适的数据库以解决数据存储与处理问题呢?这里提供以下几点作为判断依据。
一个项目并非只选择一种数据库,可以将其拆开设计,将需要 RDB 特性的放到 RDB 中管理,而其它数据放到 NoSQL 中管理。数据模型的关联性要求
比如,对微博数据的处理就不需要太高的事务性,但是对数据的存取性能有很高的要求,这时就非常适合使用 MongoDB。
因为 MongoDB 能高效的处理数据,所以非常适合作为缓存层来使用。将 MongoDB 作为持久化缓存层,可以避免底层存储的资源过载。
对关系型数据库而言,当表的大小达到一定数量级后,其性能会急剧下降。这时可以使用多台 MongoDB 服务器搭建一个集群环境,实现最大程度的扩展,且不影响性能。
mongod --dbpath="C:\mongodb"
# mongod 默认监听 127.0.0.1:27017。
win+R,然后输入 services.msc 打开。
启动、停止、暂停、恢复、重新启动
mongo Shell 是 MongoDB 官方提供的一个在命令行中用来连接操作 MongoDB 服务的客户端工具.使用 mongo Shell 可以对 MongoDB 数据库进行数据的管理
您可以在没有任何命令行选项的情况下运行 mongo shell,以使用默认端口 27017 连接到在本地主机上运行的 MongoDB 实例:
mongosh
要明确指定端口,请包括 --port 命令行选项。例如,要使用非默认端口 28015 连接到在 localhost 上运行的 MongoDB 实例,请执行以下操作:
mongosh --port 28015
连接远程主机上的 MongoDB 服务需要明确指定主机名和端口号。
您可以指定一个连接字符串。例如,要连接到在远程主机上运行的 MongoDB 实例,请执行以下操作:
mongo "mongodb://mongodb0.example.com:28015"
您可以使用命令行选项 --host <主机>:<端口>。例如,要连接到在远程主机上运行的 MongoDB 实例,请执行以下操作:
mongosh --host mongodb0.example.com:28015
您可以使用–host 和–port 命令行选项。例如,要连接到在远程主机上运行的MongoDB实例,请执行以下操作:
mongosh --host mongodb0.example.com --port 28015
您可以在连接字符串中指定用户名,身份验证数据库以及可选的密码。例如,以alice用户身份连接并认证到远程MongoDB实例:
mongosh "mongodb://alice@mongodb0.examples.com:28015/?authSource=admin"
您可以使用–username 和–password,–authenticationDatabase 命令行选项。例如,以alice用户身份连接并认证到远程MongoDB实例:
mongosh --username alice --password --authenticationDatabase admin --host mongodb0.examples.com --port 28015
注意:如果您指定–password而不输入用户密码,则外壳程序将提示您输入密码。
由于 MongoDB 是文档型数据库,其中存储的数据就是熟悉的 JSON 格式数据。
{
// 数据库 Database
"京东": {
// 集合 Collection,对应关系型数据库中的 Table
"用户": [
// 文档 Document,对应关系型数据库中的 Row
{
// 数据字段 Field,对应关系数据库中的 Column
"id": 1,
"username": "张三",
"password": "123"
},
{
"id": 2,
"username": "李四",
"password": "456"
}
// ...
],
"商品": [
{
"id": 1,
"name": "iPhone Pro Max",
"price": 100
},
{
"id": 2,
"name": "iPad Pro",
"price": 80
}
],
"订单": []
// ...
},
// 数据库
"淘宝": {}
// ...
}
show dbs
db
use <DATABASE_NAME>
集合类似于关系数据库中的表,MongoDB 将文档存储在集合中。
db.myNewCollection2.insert( { x: 1 } )
show collections
db.集合名称.drop()
show dbs
show dbs
集合名称应以下划线或字母字符开头,并且:
文档对字段名称有以下限制:
字段的值可以是任何 BSON 数据类型,包括其他文档,数组和文档数组。例如,以下文档包含各种类型的值:
在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略 _id 字段,则 MongoDB 驱动程序会自动为 _id 字段生成 ObjectId。
_id 字段具有以下行为和约束:
在掌握了 MongoDB 中的基础概念之后,下面我们开始学习数据的增删改查,简称 CRUD。
db.inventory.find()
//插入单个
db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
//插入多个
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
{ item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
{ item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])
//插入单个 建议用insertOne(它会返回id)
db.inventory.insert(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
//插入多个 建议用insertMany(它会返回id)
db.inventory.insert(
[
{ item: "canvas111", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } },
{ item: "canvas222", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
]
)
db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
// 第二个参数是查询条件 1表示查询 0表示不查询
db.inventory.find({},{item:0})
// 查询status为A的数据
db.inventory.find({status:'A'})
// 查询与 : status为A & qty为45的数据
db.inventory.find({status:'A',qty:45})
// 查询或 : status为A 或 qty为45的数据
db.inventory.find({
$or:[
{status:'A'},
{qty:45}
]
})
// 查询status为A且qty小于30或item是p开头的数据
db.inventory.find({
status: "A",
$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
})
// 查询大于等于50的数据
db.inventory.find( { qty: { $gte: 50 } })
// 查询嵌套文档 字段顺序和字段数都要与数据库中的一致
db.inventory.find({
size: { h: 14, w: 21, uom: "cm" }
})
// 查询size 字段中的 uom 字段等于 "in" 的所有文档
db.inventory.find({
"size.uom": "in"
})
// 查询size 字段中的 w 字段小于12的所有文档
db.inventory.find({
"size.w":{$lt:12}
})
// 查询选择嵌套字段 h 小于 15,嵌套字段 uom 等于 "in",状态字段等于 "D" 的所有文档
db.inventory.find({
"size.h": { $lt: 15 },
"size.uom": "in",
status: "D"
})
db.inventory.drop()
db.inventory.find()
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
{ item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
{ item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
{ item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
{ item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);
// 匹配一个数组
//要在数组上指定相等条件,请使用查询文档 {<field>: <value>},其中 <value> 是要匹配的精确数组,包括元素的顺序。
//下面的示例查询所有文档,其中字段标签值是按指定顺序恰好具有两个元素 "red" 和 "blank" 的数组
db.inventory.find({
tags:["red","blan"]
})
//不考虑顺序或该数组中的其他元素,请使用 $all 运算符:
db.inventory.find({
tags: { $all: ["red", "blank"] }
})
// 查询数组中的元素
// 以下示例查询所有文档,其中 tag 是一个包含字符串 "red" 作为其元素之一的数组:
db.inventory.find({
tags: "red"
})
// 为数组元素指定多个条件
// 使用数组元素上的复合过滤条件查询数组
// 个元素可以满足大于 15 的条件,而另一个元素可以满足小于 20 的条件;或者单个元素可以满足以下两个条件
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
// 查询满足多个条件的数组元素
// 以下示例查询在 dim_cm 数组中包含至少一个同时 大于22 和 小于30 的元素的文档
db.inventory.find({
dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } }
})
// 通过数组索引位置查询元素
// 下面的示例查询数组 dim_cm 中第二个元素大于 25 的所有文档
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
// 通过数组长度查询数组
// 使用 $size 运算符可按元素数量查询数组。
//例如,以下选择数组标签具有3个元素的文档。
db.inventory.find( { "tags": { $size: 3 } } )
db.inventory.drop()
db.inventory.insertMany( [
{ item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
{ item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
{ item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
{ item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
//查询嵌套在数组中的文档
//以下示例选择库存数组中的元素与指定文档匹配的所有文档:
db.inventory.find({
"instock": { warehouse: "A", qty: 5 }
})
//整个嵌入式/嵌套文档上的相等匹配要求与指定文档(包括字段顺序)完全匹配。例如,以下查询与库存收集中的任何文档都不匹配:
db.inventory.find({
"instock": { qty: 5, warehouse: "A" }
})
//在文档数组中的字段上指定查询条件
//下面的示例选择所有库存数组中包含至少一个嵌入式文档的嵌入式文档,这些嵌入式文档包含值小于或等于20的字段qty
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
// 使用数组索引在嵌入式文档中查询字段
// 下面的示例选择所有库存文件,其中库存数组的第一个元素是包含值小于或等于20的字段qty的文档:
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
// 为文档数组指定多个条件
// 下面的示例查询库存数组中至少有一个嵌入式文档的文档,这些文档同时包含等于5的字段qty和等于A的字段仓库:
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
// 下面的示例查询库存数组中至少有一个嵌入式文档的嵌入式文档包含的字段qty大于10且小于或等于20:
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
// 元素组合满足标准
//例如,以下查询匹配文档,其中嵌套在库存数组中的任何文档的qty字段都大于10,而数组中的任何文档(但不一定是同一嵌入式文档)的qty字段小于或等于20:
db.inventory.find( { "instock.qty": { $gt: 10, $lte: 20 } } )
//下面的示例查询库存数组中具有至少一个包含数量等于5的嵌入式文档和至少一个包含等于A的字段仓库的嵌入式文档(但不一定是同一嵌入式文档)的文档:
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
// 指定从查询返回的项目字段
db.inventory.drop()
db.inventory.insertMany( [
{ item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
{ item: "notebook", status: "A", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
{ item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
{ item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
// 返回匹配文档中所有字段
// 下面的示例返回状态为 "A" 的清单集合中所有文档的所有字段:
db.inventory.find( { status: "A" })
// 仅返回指定字段和 _id 字段
// 通过将投影文档中的 <field> 设置为 1,投影可以显式包含多个字段。以下操作返回与查询匹配的所有文档。在结果集中,在匹配的文档中仅返回项目,状态和默认情况下的 _id 字段。
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
// 禁止 _id 字段
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
// 0排除的字段
db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
//返回嵌入式文档中的特定字段
db.inventory.find(
{ status: "A" },
{ item: 1, status: 1, "size.uom": 1 }
)
// 禁止嵌入文档中的特定字段
db.inventory.find(
{ status: "A" },
{ "size.uom": 0 }
)
//在数组中的嵌入式文档上投射
db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )
//返回数组中的项目特定数组元素
db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )
//查询空字段或缺少字段
db.inventory.drop()
//查询空字段或缺少字段
db.inventory.insertMany([
{ _id: 1, item: null },
{ _id: 2 }
])
//相等过滤器
db.inventory.find( { item: null } )
//类型检查
db.inventory.find( { item : { $type: 10 } } )
//存在检查
db.inventory.find( { item : { $exists: false } } )
//更新文档
db.inventory.drop()
db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
] );
//更新单个文档
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)
//更新多个文档
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)
//替换文档
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
db.inventory.find()
//删除文档
db.inventory.drop()
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
] );
//删除所有文档
db.inventory.deleteMany({})
//删除所有符合条件的文档
db.inventory.deleteMany({ status : "A" })
//仅删除1个符合条件的文档
db.inventory.deleteOne( { status: "D" } )
db.inventory.find()
为了更好的学习 CRUD 及之后的语法,建议选择一款图形软件更方便操作。