Day 21 21.3 数据库之MongoDB

发布时间 2023-04-02 20:31:38作者: Chimengmeng

MongoDB

  • 一般爬虫使用的数据库,是根据项目来定的。

    • 如需求方指定了使用什么数据库、如果没指定,那么决定权就在爬虫程序员手里,
    • 如果自选的话,mysql 和mongodb 用的都是比较多的。
    • 但不同的数据库品种有各自的优缺点,不同的场景任何一种数据库都可以用来存储,但是某种可能会更好。
      • 比如如果抓取的数据之间的耦合性很高,关系比较复杂的话,那么mysql可能会是更好的选择。
      • 如果抓取的数据是分版块的,并且它们之间没有相似性或关联性不强,那么可能mongodb 会更好。
  • 官方文档:https://docs.mongodb.com/

  • 中文文档:https://www.mongodb.org.cn/

  • mongoDB的生态、理念非常先进而且成熟、但是mongoDB不仅有开源版本,还有企业版本。

    • 所以有部分公司比较担心,哪天无法使用mongoDB了,所以也会产生一些替代产品。
DynamoDB  : AWS
SequoiaDB : 巨杉数据库

【1】安装

(1)mac安装

  • 在 Mac OS 系统下安装 MongoDB 与在 Linux 下安装比较相似,本节我们就来详细介绍一下 Mac OS 系统下如何安装 MongoDB。

(1)下载 MongoDB

  • 与在 Linux 系统下安装 MongoDB 相同,
    • 首先我们需要在 MongoDB 的官网获得 MongoDB 安装包的下载链接,
    • 如下图所示:

图:MongoDB 官网

  • 得到下载链接后,使用cd命令进入 /usr/local 目录,
    • 然后使用wget命令下载 MongoDB 的压缩包,
    • 命令如下:

cd /usr/local

sudo wget https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.4.3.tgz

(2)安装 MongoDB

待压缩包下载完成后就可以尝试安装 MongoDB 了,具体的安装步骤如下:

  • 【步骤 1】解压缩刚刚下载的压缩包,并将其重命名为 mongodb:

sudo tar -zxvf mongodb-macos-x86_64-4.4.3.tgz # 解压 MongoDB 压缩包
sudo mv mongodb-osx-ssl-x86_64-4.0.17/ mongodb # 重命名解压得到的文件夹

  • 【步骤 2】在 /usr/local/mongodb 目录下新建两个文件夹 data 和 log,用于存储 MongoDB 的数据和日志。

sudo mkdir -p /usr/local/mongodb/data
sudo mkdir -p /usr/local/mongodb/log

使用如下命令为当前用户分配目录的读写权限:

sudo chown biancheng /usr/local/mongodb/data
sudo chown biancheng /usr/local/mongodb/log

其中“biancheng”为当前的用户名,您需要修改为您当前系统的用户名。

  • 【步骤 3】配置 PATH。在终端中输入open -e .bash_profile命令打开 bash_profile 配置文件,然后将 MongoDB 的安装目录下的 bin 目录添加到环境变量中,如下所示:

export PATH=${PATH}:/usr/local/mongodb/bin

编辑完成后保存并退出,然后使用source .bash_profile命令使配置立即生效。

  • 【步骤 4】使用下面的命令来启动 MongoDB 服务:

mongod --dbpath /usr/local/mongodb/data --logpath /usr/local/mongodb/log/mongo.log --fork

参数说明如下:

  • --dbpath 用来设置数据的存放目录;
  • --logpath 用来设置日志的存放目录;
  • --fork 用来设置在后台运行。

至此 MongoDB 就安装完成了。

(3)验证安装

  • 您可以使用mongod -version命令来验证 MongoDB 是否安装成功,
  • 如果出现类似下面所示的内容,则说明 MongoDB 安装成功。

mongod -version

db version v4.0.10
git version: c389e7f69f637f7a1ac3cc9fae843b635f20b766
allocator: tcmalloc
modules: none
build environment:
distmod: 2008plus-ssl
distarch: x86_64
target_arch: x86_64

(2)win安装

通过前面的介绍我们已经简单的了解了 MongoDB,本节我们来看看如何在 Windows 系统上安装 MongoDB。

下载 MongoDB

要在 Windows 系统上安装 MongoDB,首先需要在 MongoDB 的官网(https://www.mongodb.com/try/download/community)下载 MongoDB 的安装包,如下图所示:

图:下载 MongoDB 安装包

提示:下载前需要先注册/登陆 MongoDB 官网的账号。

安装 MongoDB

  • 【步骤 1】双击运行我们刚刚下载的 .msi 格式的 MongoDB 安装包,在弹出的窗口种单击 Next,如下图所示:

图:运行 MongoDB 安装包

  • 【步骤 2】接受用户许可协议,并单击 Next,如下图所示:

图:接受用户协议

  • 【步骤 3】单击 Custom(自定义)按钮来自定义安装,如下图所示:

图:自定义安装

  • 【步骤 4】修改安装目录,并单击 Next,如下图所示:

图:自定义安装目录

  • 【步骤 5】选中“Install MongoD as a Service”,并在下面的选项中选择“Run service as Network Service user”,完成后单击 Next,如下图所示:

图:安装 Windows 服务

图:取消“Install MongoDB Compass”的勾选

  • 【步骤 7】单击“Install”按钮开始安装。

图:开始安装

  • 【步骤 8】等待安装完成,单击“Finish”按钮退出安装程序即可完成安装。

图:完成安装

验证安装

不出意外的话,完成上面的一系列操作后 MongoDB 就成功安装到您的电脑上了。想要验证安装是否成功,您可以打开“服务”,如果能在服务列表中找到 MongoDB Server,就说明 MongoDB 已经安装成功。

【2】常用概念

(1)数据库

数据库是用于存储数据的物理容器,每个数据库在文件系统中都有属于自己的文件集。一台 MongoDB 服务器中可以创建多个数据库,并且每个数据库都是独立的,都有属于自己的集合和权限,而且不同数据库中的数据会放置在不同的文件中。

MongoDB 的默认数据库为“test”,该数据库存储在 data 目录中,您可以使用show dbs命令来查看所有的数据库列表,如下所示:

\> show dbs
admin  0.000GB
config 0.000GB
local  0.000GB

注意:在使用show dbs命令时,若数据库中没有存储任何数据,则不会在列表中显示出来,也就是说只有非空数据库才能通过show dbs命令查看。

(2)集合

集合就是一组 MongoDB 文档的组合,类似于关系型数据库(例如 MySQL)中的数据表。集合存在于数据库中,且没有固定的结构,您可以向集合中插入不同格式或类型的数据。

(3)文档

文档是 MongoDB 中数据的基本单位,由 BSON 格式(一种计算机数据交换格式,类似于 JSON)的键/值对组成,类似于关系型数据库中的一行行数据,但要相对复杂一些。

文档具有动态模式,所谓动态模式就是同一集合中的文档不需要具有相同的字段,即使是相同的字段也可以是不同的类型,这与关系型数据库有很大的区别,也是 MongoDB 最突出的特点之一。

下表列举了关系型数据库与 MongoDB 中的一些差异:

关系型数据库 MongoDB 解释说明
database database 数据库
table collection 数据表/集合
row document 数据行/文档
column field 字段/域
index index 索引
table joins 表连接,MongoDB 中不支持
primary key primary key 主键,MongoDB 会自动将 _id 字段设置为主键

【3】数据库操作

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
> use blog
switched to db blog
> db
blog
> db.article.insert({"title":"mongodb"})
WriteResult({ "nInserted" : 1 })
> use shop
switched to db shop
> db.goods.insert({"name":"电子商品"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin   0.000GB
blog    0.000GB
config  0.000GB
local   0.000GB
shop    0.000GB
> db.dropDatabase()
{ "dropped" : "shop", "ok" : 1 }

【4】集合操作

  • MongoDB 的集合就相当于 MySQL 的一个表 table,
  • MySQL 列出的所有表都可以使用 show tables,
  • MongoDB 可以使用 show collections 展示所有集合
> db
shop
> db.createCollection("menu")
{ "ok" : 1 }
> db.menu.insert({"id":"1231231","name":"张三"})
WriteResult({ "nInserted" : 1 })
> db.menu.find()
{ "_id" : ObjectId("6425263f8ae74e12d95c4c7e"), "id" : "1231231", "name" : "张三" }
> db.menu.insert({"id":"1231231","name":"李四","price":199})
WriteResult({ "nInserted" : 1 })
> db.menu.find()
{ "_id" : ObjectId("6425263f8ae74e12d95c4c7e"), "id" : "1231231", "name" : "张三" }
{ "_id" : ObjectId("642526968ae74e12d95c4c7f"), "id" : "1231231", "name" : "李四", "price" : 199 }
> show tables;
menu
> show collections;
menu
> db.menu.drop()
true
> show tables;
> 

【5】文档操作

文档是 MongoDB 中存储的基本单元,是一组有序的键值对集合。文档中存储的文档键的格式必须是符合 UTF-8 标准的字符串。

添加文档

语法

db_name.collection_name.insert(
	<document or array of documents>,
	{
	    writeConcern: <document>,    //可选字段
	    ordered: <boolean>    //可选字段
	}
)

参数

参数 描述
db_name 数据库名
collection_name 集合名
document or array of documents 表示可设置插入一条或多条文档
writeConcern 参数表示自定义写出错的级别,是一种出错捕捉机制
ordered 是可选的,默认为 true

在插入时,我们既可以指定 _id 的值,如果指定了,则该值必须唯一,如果没有指定,则系统默认生成唯一的值ObjectId。

#插入单条
user1={
    "name":"张三",
    "age":22,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'BJ'
    }
}
 
db.user.insert(user1)
db.user.find()
 
#3、插入多条
user2={
    "name":"李四",
    "age":23,
    'hobbies':['music','read','dancing'],
    'addr':{
        'country':'China',
        'city':'珠海'
    }
}
 
user3={
  
    "name":"王五",
    "age":20,
    'hobbies':['music','read'],
    'addr':{
        'country':'China',
        'city':'廊坊'
    }
}

user4={
   
    "name":"赵六",
    "age":32,
    'hobbies':['read','run'],
    'addr':{
        'country':'China',
        'city':'大连'
    }
}

user5={
   
    "name":"朱七",
    "age":35,
    'hobbies':['run'],
    'addr':{
        'country':'China',
        'city':'青岛'
    }
}
 
db.user.insertMany([user2,user3,user4,user5]) 
# db.user.find().pretty()

查看文档

(1) 比较运算 
 
# SQL:=,!=,>,<,>=,<=
# MongoDB:{key:value}代表什么等于什么,"$ne","$gt","$lt","gte","lte",其中"$ne"能用于所有数据类型
 
#1、select * from db.user where name = "张三";
db.user.find({'name':'张三'})
 
#2、select * from db.user where name != "alex";
db.user.find({'name':{"$ne":'张三'}})
 
#3、select * from db.user where age > 30;
db.user.find({'age':{'$gt':30}})
 
 
(2) 逻辑运算 
 
# SQL:and,or,not
# MongoDB:字典中逗号分隔的多个条件是and关系,"$or"的条件放到[]内,"$not"
 
db.user.find({'age':{"$gte":20,"$lt":33}})
 
db.user.find({"addr.city":"青岛","age":{"$gt":30}})
 
db.user.find({
    "$or":[
        {"addr.city":"青岛"},
        {"age":{"$gt":30}}
        ]
})
 
#4、select * from db1.user where id % 2=1;
db.user.find({'age':{"$mod":[2,1]}})
 
#5、上题,取反
db.user.find({'age':{"$not":{"$mod":[2,1]}}})
 
 
(3) 成员运算 
 
# SQL:in,not in
# MongoDB:"$in","$nin"
 
db.user.find({"age":{"$in":[20,30,40]}})
 
db.user.find({"name":{"$nin":['张三','']}})
 
 
(4) 正则匹配
 
# SQL: regexp 正则
# MongoDB: /正则表达/i

db.user.find({'name':/^张.*/i})
 
(5) 取指定字段  

db.user.find({'name':/^张.*/i},{'_id':0,'name':1,'age':1})
 
(6) 查询数组 
 
# 查看有dancing爱好的人
db.user.find({'hobbies':'dancing'})
 
# 查看既有dancing爱好又有music爱好的人
db.user.find({
    'hobbies':{
        "$all":['music','dancing']
        }
})
 
 
 (7) 排序 
 
# 排序:--   1代表升序,  -1代表降序
db.user.find().sort({"name":1,})
db.user.find().sort({"age":-1,'_id':1})
 
 (8) 分页 
 
# 分页:--limit代表取多少个document,skip代表跳过前多少个document。
db.user.find().limit(1).skip(2)
 
 (9) 查询数量 
# 获取数量
db.user.count({'age':{"$gt":30}})
 
--或者
db.user.find({'age':{"$gt":30}}).count()
 
 (10) 其它  
 
# 查找所有
db.user.find() #等同于db.user.find({})
db.user.find().pretty()
 
#3、查找一个,与find用法一致,只是只取匹配成功的第一个
db.user.findOne({"_id":{"$gt":3}}) 

更新文档

(1) update的语法

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

参数说明:对比update db1.t1 set name='EGON',sex='Male' where name='egon' and age=18;

query : 相当于where条件。
update : update的对象和一些更新的操作符(如$,$inc...等,相当于set后面的
upsert : 可选,默认为false,代表如果不存在update的记录不更新也不插入,设置为true代表插入。
multi : 可选,默认为false,代表只更新找到的第一条记录,设为true,代表更新找到的全部记录。
writeConcern :可选,抛出异常的级别。

更新操作是不可分割的:若两个更新同时发送,先到达服务器的先执行,然后执行另外一个,不会破坏文档。


(1) 覆盖更新 
 
#注意:除非是删除,否则_id是始终不会变的
#1 :
db.user.update({'age':20},{"name":"xxx"})
是用{"_id":2,"name":"xxx"}覆盖原来的记录
 
#2、一种最简单的更新就是用一个新的文档完全替换匹配的文档。这适用于大规模式迁移的情况。例如
var obj=db.user.findOne({"name":"张三"})
 
obj.name=obj.name+'先生'
obj.age++
delete obj.hobbies
 
db.user.update({"nmae":"张三"},obj)
 
(2) 局部更新  
 
#设置:$set
 
通常文档只会有一部分需要更新。可以使用原子性的更新修改器,指定对文档中的某些字段进行更新。
更新修改器是种特殊的键,用来指定复杂的更新操作,比如修改、增加后者删除
 
db.user.update({'name':"xxx"},{"$set":{"name":"apple",}})
 
# 没有匹配成功则新增一条{"upsert":true}
db.user.update({'name':"eric"},{"$set":{"name":"eirc","age":18}},{"upsert":true})
 
# 默认只改匹配成功的第一条,{"multi":改多条}
db.user.update({'age':{"$gt":20}},{"$set":{"age":18}})
db.user.update({'age':{"$gt":20}},{"$set":{"age":18}},{"multi":true})

# 
db.user.update({'name':"朱七"},{"$set":{"hobbies.1":"swimming"}})

db.user.update({'name':"朱七"},{"$unset":{"hobbies":""}})
 
(3) 自增或自减  
 
#增加和减少:$inc
 
#1、所有人年龄增加一岁
db.user.update({},
    {
        "$inc":{"age":1}
    },
    {
        "multi":true
    }
    )
#2、所有人年龄减少5岁
db.user.update({},
    {
        "$inc":{"age":-5}
    },
    {
        "multi":true
    }
    )
 
 
(4) 添加删除数组内元素
 
#添加删除数组内元素:$push,$pop,$pull
     
往数组内添加元素:$push
# 为名字为朱七添加一个爱好pingpong
db.user.update({"name":"zhuqi"},{"$push":{"hobbies":"pingpong"}})
 
 
# 按照条件删除元素,:"$pull" 把符合条件的统统删掉,而$pop只能从两端删
db.user.update({'addr.country':"China"},{"$pull":{
    "hobbies":"read"}
},
{
    "multi":true
}
)
 
(5) 避免重复添加
 
#避免添加重复:"$addToSet"
 
db.urls.insert({"_id":1,"urls":[]})
 
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
 
db.urls.update({"_id":1},{
    "$addToSet":{
        "urls":{
        "$each":[
            'http://www.baidu.com',
            'http://www.baidu.com',
            'http://www.xxxx.com'
            ]
            }
        }
    }
)

删除文档

#1、删除多个中的第一个
db.user.deleteOne({ 'age': 8 })
 
#2、删除国家为China的全部
db.user.deleteMany( {'addr.country': 'China'} )
 
#3、删除全部
db.user.deleteMany({})