文章目录
- NoSql
- MongoDb
-
- 笛卡尔集
- mysql与mongodb逻辑结构对比
- mongodb社区版下载地址
- [windows mongodb7.0配置安装](#windows mongodb7.0配置安装)
- [linux mongodb4.0.5配置安装](#linux mongodb4.0.5配置安装)
- 数据库与集合的基础操作
- mongodb数据类型
- 数据的新增
- 数据的查询
- 数组嵌套查询
- 修改与删除
-
- 修改
- 删除字段
- 向数组添加
-
- [set](#set)
- \$addToSet
- \$push不判断重复
- \$pull删除
- \$pop删除
- \$elemMatch
- 只会更新第一条
- [更新所有 匹配的条件](#更新所有 匹配的条件)
NoSql
分类
键值(Key-Value)存储数据库
这类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value模型对于IT系统来说的优势在于简单、易部署。但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下。举例:Tokyo Cabinet/Tyrant,Redis,Voldemort,Oracle BDB
列存储数据库
这部分数据库通常是用来应付分布式存储的海量数据。键仍然存在,但是它们的特定是指向了多个列。这些列是由列家族来安排的。如:Cassandra,HBase,Riak
文档型数据库
文档型数据库的灵感是来自于Lotus Notes办公软件,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB,MongoDb。国内也有文档型数据库SequoiaDB,已经开源。
图形(Graph)数据库
图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。如:Neo4J,InfoGrid,Infinite Graph
NoSql的应用场景
1.数据模型比较简单
2.需要灵活性更强的IT系统
3.对数据库性能要求较高
4.不需要高度的数据一致性
MongoDb
笛卡尔集
在探讨MySQL和MongoDB在处理电影表、影评表、影评评论表时为何一个可能出现笛卡尔集而另一个不会的问题时,我们首先要理解这两种数据库的本质区别。
MySQL(关系型数据库)
数据结构:MySQL是关系型数据库,数据以表格形式严格定义,并通过SQL语言进行查询。表与表之间存在明确的关系,通常通过主键和外键来维护。
笛卡尔集问题:当在MySQL中进行多表连接查询时,如果没有明确指定连接条件(如使用WHERE子句或JOIN条件),系统会返回所有可能的组合,即笛卡尔集。这是因为关系型数据库通过表之间的关联来组织和查询数据。
示例:假设有电影表和影评表,如果没有正确指定连接条件,查询结果将是两部表中所有记录的组合,这通常会导致数据量巨大且不包含有效信息的结果集。
MongoDB(文档型数据库)
数据结构:MongoDB是文档型数据库,使用BSON(Binary JSON)格式存储数据。它不依赖于固定的表结构,而是存储自包含的文档。每个文档可以有不同的字段和结构。
避免笛卡尔集:在MongoDB中,数据通常以嵌套文档或数组的形式组织,这意味着相关信息被整合在同一个文档中。由于不存在严格的表结构,因此在进行查询时,不需要像关系型数据库那样进行表连接操作。这种数据模型自然地避免了笛卡尔集的问题。
示例:在MongoDB中,一部电影的信息和它的影评可以被组织在同一个文档中,或者通过某种方式关联(如使用电影ID作为影评文档中的一个字段)。这样,在查询时就不会产生无关的组合。
总结
MySQL等关系型数据库在处理多表查询时需要明确指定连接条件,否则会产生笛卡尔集。
MongoDB的文档型数据模型使得相关数据可以自然地组织在一起,从而避免了笛卡尔集的问题。
在设计数据库和编写查询时,了解这两种数据库的不同特性和最佳实践是非常重要的。
综上所述,虽然MySQL和MongoDB都可以用来存储和查询电影、影评等相关信息,但由于它们的数据模型和查询方式的不同,MongoDB在处理这类数据时不会遇到MySQL中可能出现的笛卡尔集问题。
mysql与mongodb逻辑结构对比
数据库对应数据库
表对应集合
数据行对应文档
字段对应字段
外键对应嵌套文档
关系型数据库 | MongoDb |
---|---|
database(数据库) | database(数据库) |
table (表) | collection( 集合) |
row( ⾏) | document( BSON ⽂档) |
column (列) | field (字段) |
index(唯⼀索引、主键索引) | index (全⽂索引) |
join (主外键关联) | embedded Document (嵌套⽂档) |
primary key(指定1⾄N个列做主键) | primary key (指定_id field做为主键) |
aggreation(groupy) | aggreation (pipeline mapReduce) |
mongodb社区版下载地址
https://www.mongodb.com/download-center/community
windows mongodb7.0配置安装
mongoshell下载地址
https://www.mongodb.com/try/download/shell
powershell
mongosh
windows下创建名为mongod.cfg的配置文件
powershell
systemLog:
destination: file
path: C:\Program Files\MongoDB\Server\7.0\log\mongod.log
logAppend: true
storage:
dbPath: C:\Program Files\MongoDB\Server\7.0\data
net:
bindIp: 127.0.0.1
port: 27017
运行mongodb
powershell
mongod --config "C:\Program Files\MongoDB\Server\7.0\mongod.cfg"
检查mongodb服务状态
powershell
services.msc
linux mongodb4.0.5配置安装
powershell
#下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.5.tgz
# 解压
tar -zxvf mongodb-linux-x86_64-4.0.5.tgz
#创建数据库目录
mkdir -p /data/mongo
# 启动mongo
./bin/mongod --dbpath=/data/mongo/
常规参数
参数 | 说明 |
---|---|
dbpath | 数据库⽬录,默认/data/db |
bind_ip | 监听IP地址,默认全部可以访问 |
port | 监听的端⼝,默认27017 |
logpath | ⽇志路径 |
logappend | 是否追加⽇志 |
auth | 是否开启⽤户密码登陆 |
fork | 是否已后台启动的⽅式登陆 |
config | 指定配置⽂件 |
配置文件示例和以配置文件方式启动
powershell
vim mongo.conf
powershell
dbpath=/data/mongo/
port=27017
bind_ip=0.0.0.0
fork=true
logpath = /data/mongo/mongodb.log
logappend = true
auth=false
powershell
./bin/mongod -f mongo.conf
客户端shell的使用及参数说明
powershell
#启动客户端 连接 本机的地的默认端口
./bin/mongo
# 指定IP和端口
./bin/mongo --host=127.0.0.1 --port=27017
mongo shell 是⼀个js 控台,可以执⾏js 相关运算
powershell
db.createUser({ user: "root", pwd: "123456", roles: [{ role: "dbOwner", db: "commentDB" }] });
数据库与集合的基础操作
powershell
#查看数据库
show dbs;
#切换数据库
use dd;
#创建数据库与集合,在插入数据时会自动 创建数据库与集和
db.self.insertOne({name:"dd",sex:"man"});
#查看集合
show tables;
show collections;
#删除集合
db.self.drop();
#删除数据库
db.dropDatabase()
mongodb数据类型
字符串 整型 布尔 浮点型 日期类型
Date():日期类型的字符串
new Date():日期类型
数据的新增
关于Mongodb数据插⼊的说明
1.数据库的新增不需要序先设计模型结构,插⼊数据时会⾃动创建。
2.同⼀个集合中不同数据字段结构可以不⼀样
powershell
指定ID
db.self.insert([
{_id:1,name:"dd",sex:"man",age:1},
{_id:2,name:"dd",sex:"women",birthday:new Date("1999-11-
11")}
数据的查询
概要:
a. 基于条件的基础查询
b. and、or、in、gt、gte、lt、$lte 运算符
c. 基于 sort skip limit ⽅法实现排序与分⻚
d. 嵌套查询
e. 数组查询
f. 数组嵌套查询
逻辑运算:and、or
其值为多个逻辑的组合运算,后⾯跟中括号,中括号包括多个⼤括号。
值运算:in、gt、gte、lt、$lte $all
基于具体的值进⾏运算
powershell
#基于ID查找
db.emp.find({_id:001})
#基于属性查找
db.emp.find({"name":"dd"})
# && 运算 与大于 运算
db.emp.find({"job":"程序员","salary":{$gt:8000}})
# in 运算
db.emp.find({"job":{$in:["程序员","客服"]}})
# or 运算
db.emp.find({$or:[{job:"程序员" },{job:"客服"}] })
排序与分页
powershell
db.emp.find().sort({dep:1,salary:-1}).skip(6).limit(3)
基于复合属性查找
powershell
基于复合属性查找 时必须包含其所有的值 并且顺序一致
db.student.find({grade:{math:87,english:85,physics:90} })
#基于复合属性当中的指定值 查找。注:名称必须用双引号
db.student.find({"grade.math":87});
db.student.find({"grade.math":{"$gt":80}});
基于数组查询
powershell
db.subject.insertMany([
{_id:"001",name:"张三",subjects:["math","english","physics"]},
{_id:"002",name:"李四",subjects:["math","english"]},
{_id:"003",name:"王五",subjects:["chemistry","biology","medicine"]},
{_id:"004",name:"王三",subjects:["languistics","literature","sociology"]},
])
powershell
# 与嵌套查询一样,必须是所有的值 并且顺序一至
db.subject.find({subjects:["math","english","physics"]})
# $all 匹配数组中包含该两项的值。注:顺序不作要求
db.subject.find({subjects:{"$all": ["math","english"]}})
注:
# 简化数组查询
db.subject.find({subjects:"math"})
# 简化数组查询 ,匹配数组中存在任意一值。与$all相对应
db.subject.find({subjects:{$in: ["math","english"]}})
数组嵌套查询
powershell
{
"_id": ObjectId("..."),
"subjects": [
{
"name": "redis",
"hour": 12
},
{
"name": "mysql",
"hour": 120
},
{
"name": "mongodb",
"hour": 8
}
]
}
powershell
#基础查询 ,必须查询全部,且顺序一致
#这个查询会匹配subjects数组中有一个对象其name为"redis"且hour为12的文档
#上面的文档满足这个条件。
db.subject2.find({subjects:{name:"redis",hour:12} })
#这个查询会匹配subjects数组的第一个元素的hour字段大于12的文档
#上面的文档不满足这个条件,但如果您调整数组元素的顺序,将hour大于12的对象放在第一个位置,它就会满足这个条件。注意,这个查询是依赖于数组元素的顺序的
db.subject2.find({"subjects.0.hour":{$gt:12}})
#这个查询会匹配subjects数组中有任何一个对象的hour字段大于12的文档。上面的文档满足这个条件,因为mysql的课时是120。
db.subject2.find({"subjects.hour":{$gt:12}})
# $elemMatch 元素匹配,指定属性满足,且不要求顺序一致
#这个查询使用$elemMatch操作符来匹配subjects数组中有一个对象其name为"redis"且hour为12的文档。上面的文档满足这个条件。
db.subject2.find({subjects:{$elemMatch:{name:"redis",hour:12}}})
# 数组中任意元素匹配 不限定在同一个对象当中
#这个查询会匹配subjects数组中有对象的name为"mysql"且有其他对象的hour为120的文档。注意,这两个条件不需要在同一个对象上满足。上面的文档满足这个条件。
db.subject2.find({"subjects.name":"mysql","subjects.hour":120})
修改与删除
修改
powershell
db.表.update(条件,{设置值},false,false)
删除字段
powershell
db.subjects2.update({"_id":"001"},{$unset:{"subjects":1}})
在MongoDB中,_id 字段通常是一个 ObjectId 类型,而不是一个简单的字符串如 "001"。如果你确实有一个文档的 _id 字段是字符串 "001",那么这条命令是可以正常工作的。不过,通常情况下,_id 是一个 ObjectId 的实例。
解析该命令:
db.subjects2.update(...): 这表示你要更新 subjects2 这个集合中的文档。
{"_id":"001"}: 这是查询条件,表示你要更新 _id 字段值为 "001" 的文档。如果你的 _id 是 ObjectId 类型,你需要确保这里的值与实际的 ObjectId 字符串相匹配。
{unset:{"subjects":1}}: 这是更新的操作。unset 是 MongoDB 的一个更新操作符,用于从文档中移除指定的字段。在这里,它试图从匹配的文档中移除 subjects 字段。
所以,这条命令的作用是:
在 subjects2 集合中,找到 _id 为 "001" 的文档(或者是一个具体的 ObjectId 字符串,如果你的 _id 是这种类型)。
从该文档中移除 subjects 字段及其值。
如果 _id 字段实际上是 ObjectId 类型,并且你想要根据一个具体的 ObjectId 来更新文档,你需要将命令修改为类似于以下内容(假设你的 ObjectId 是 ObjectId("507f191e810c19729de860ea")):
javascript
db.subjects2.update({"_id": ObjectId("507f191e810c19729de860ea")}, {$unset: {"subjects": ""}})
注意,在 $unset 中,字段名的值可以是空字符串 "" 或者数字 1,两者在这里的效果是相同的。都是指示 MongoDB 移除该字段。在最新的 MongoDB 版本中,推荐使用空字符串 "" 作为\ $unset 的值。
如果你的 _id 确实是一个简单的字符串,比如 "001",并且你想要移除 subjects 字段,那么你提供的命令就是正确的。
向数组添加
$set
如果你想使用$set 操作符来更新 subject2 集合中的文档,你需要注意 $set 和 addToSet 在功能上的区别。addToSet 用于向数组添加一个新元素,但仅当该元素不在数组中时才添加。而 set 操作符用于设置指定字段的值,如果字段不存在,set 将创建一个新字段,使用 $set 不会检查数组中是否已经存在相同的元素。
如果你确定要使用 $set 来更新 subjects 字段,并且你知道你想要设置的确切数组结构,你可以这样做。但是,请注意,这将直接替换 subjects 数组的当前内容,而不是向数组中添加一个新元素。
以下是如何使用 $set 来更新 subjects 字段的示例:
powershell
db.subject2.update(
{id: "002"},
{$set: {subjects: [{name: "redis", hour: 30}, {name: "dubbo", hour: 50}, {name: "mongodb", hour: 40}]}}
)
在这个例子中,subjects 数组被设置为一个新的数组,其中包含三个对象。如果 id 为 "002" 的文档原先有其他 subjects,它们将被这个新数组完全替换。
如果你只是想用 $set 添加或修改数组中的特定元素,而不是替换整个数组,你需要指定数组索引。例如,如果你想设置 subjects 数组的第一个元素,你可以这样做:
powershell
db.subject2.update(
{id: "002"},
{$set: {"subjects.0": {name: "dubbo", hour: 50}}}
)
这将把 id 为 "002" 的文档的 subjects 数组的第一个元素设置为 {name: "dubbo", hour: 50}。如果数组索引超出当前数组长度,MongoDB 将不会执行任何操作。
请注意,这种方法需要你知道你想要更新的数组元素的确切索引,而且它会替换指定索引处的元素,而不是添加一个新元素。如果你不确定数组的结构或长度,使用 $addToSet 通常更安全,因为它会确保不会添加重复的元素。
$addToSet
powershell
db.subject2.update({id:"002"},{$addToSet:{subjects: {name:"dubbo",hour:50}}})
这条命令的意图是向id为"002"的文档的subjects数组中添加一个新的课程对象,但仅当这个课程对象在数组中尚不存在时。
powershell
{
"_id": ObjectId("..."),
"id": "002",
"subjects": [
{
"name": "redis",
"hour": 30
},
{
"name": "mongodb",
"hour": 40
}
// 注意,此时还没有 {name:"dubbo",hour:50} 这个对象
]
}
在执行了 db.subject2.update({id:"002"},{$addToSet:{subjects: {name:"dubbo",hour:50}}}) 命令后,文档将被更新为:
powershell
{
"_id": ObjectId("..."),
"id": "002",
"subjects": [
{
"name": "redis",
"hour": 30
},
{
"name": "mongodb",
"hour": 40
},
{
"name": "dubbo",
"hour": 50
}
// {name:"dubbo",hour:50} 已经被添加到 subjects 数组中
]
}
$push不判断重复
$pull删除
$pop删除
$elemMatch
只会更新第一条
db.emp.update({"dep":"技术部"},{$inc:{salary:100}})
更新所有 匹配的条件
db.emp.updateMany({"dep":"技术部"},{$inc:{salary:100}})