九:爬虫-MongoDB基础

MongoDB介绍

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引

为什么要使用nosql

  • Nosql简介
    • NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
    • NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
  • 发展现状
    • 现今的计算机体系结构在数据存储方面要求应用架构具备庞大的水平扩展性,而NoSQL正在致力于改变这一现状。目前新浪微博的 RedisGoogleBigtable 以及 AmazonSimpleDB使用的就是 NoSQL 型数据库
    • NoSQL 项目的名字上看不出什么相同之处,但是,它们通常在某些方面相同:它们可以处理超大量的数据
    • 这场革命目前仍然需要等待。NoSQL 对大型企业来说还不是主流,但是,一两年之后很可能就会变个样子。在 NoSQL 运动的最新一次聚会中,来自世界各地的 150 人挤满了 CBS Interactive 的一间会议室。分享他们如何推翻缓慢而昂贵的关系数据库的暴政,怎样使用更有效和更便宜的方法来管理数据
    • 关系型数据库给你强加了太多东西。它们要你强行修改对象数据,以满足数据库系统的需要。在 NoSQL 拥护者们来看,基于 NoSQL 的数据库替代方案"只是给你所需要的"
  • Nosql特点
    • 1 它可以处理超大量的数据
    • 2 它运行在便宜的 PC 服务器集群上 PC
      • 集群扩充起来非常方便并且成本很低,避免了传统商业数据库"sharding"操作的复杂性和成本。
    • 3 它击碎了性能瓶颈
      • NoSQL 的支持者称,通过 NoSQL 架构可以省去将 WebJava 应用和数据转换成 SQL 格式的时间,执行速度变得更快。"SQL并非适用于所有的程序代码",对于那些繁重的重复操作的数据,SQL 值得花钱。但是当数据库结构非常简单时,SQL 可能没有太大用处
    • 4 它没有过多的操作
      • 虽然 NoSQL 的支持者也承认关系型数据库提供了无可比拟的功能集合,而且在数据完整性上也发挥绝对稳定,他们同时也表示,企业的具体需求可能没有那么复杂
    • 5 它的支持者源于社区
      • 因为 NoSQL 项目都是开源的,因此它们缺乏供应商提供的正式支持。这一点它们与大多数开源项目一样,不得不从社区中寻求支持
  • MongoDB特点
    • 1 面向集合(Collenction-Orented
      • 意思是数据被分组存储在数据集中, 被称为一个集合(Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表(table),不同的是它不需要定义任何模式(schema)
    • 2 模式自由(schema-free)
      • 意味着对于存储在 MongoDB 数据库中的文件,我们不需要知道它的任何结构定义。提了这么多次"无模式"或"模式自由",它到是个什么概念呢?例如,下面两个记录可以存在于同一个集合里面: {"welcome" : "Beijing"} {"age" : 25}
    • 3 文档型
      • 意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 "BSON" 即 "Binary Serialized document Notation."

MongoDB下载与安装

MongoDB官网

启动MongoDB

终端命令: mongod --dbpath C:\Program Files\MongoDB\Server\4.4\data

连接MongoDB

  • 在环境变量设置好的前提下,在终端输入命令mongo就可以进入到mongo的操作终端了。

配置环境变量参考如下: https://blog.csdn.net/Alisa_Sheng/article/details/122621415

  • 图例所示:

MongoDB概念解析

不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库,下面我们挨个介绍

下表将帮助您更容易理解Mongo中的一些概念:

MongoDB三要素

  • 数据库:一个集合的物理容器,一个数据库可以包含多个文档(一个服务器通常有多个数据库)。
  • 文档:就是关系型数据库中的一行。文档是一个对象,由键值对构成,是json的扩展形式
  • 集合:类似于关系型数据库中的表,集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性

MongoDB数据类型

  • String:字符串,必须是有效的UTF-8
  • Boolean:存储一个布尔值,true或者false
  • Integer:整数可以是32位或64位,这取决于服务器
  • Double:存储浮点数
  • Arrays:数组或列表
  • Object:嵌入式文档
  • Null:存储Null
  • Timestamp:时间戳, 表示从1970-1-1到现在的总秒数
  • Object ID是一个12字节的十六进制数

MongoDB操作数据库的常用命令(掌握)

  • show dbs 查看所有数据库
  • db 查看现在用的数据库 (MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。)
  • cls 清屏的命令
  • use admin 如果数据库不存在,则创建数据库,否则切换到指定数据库。


注意: 我们刚创建的数据库 demo01并不在数据库的列表中, 要显示它,我们需要向 demo01数据库插入一些数据

  • db.dropDatabase() 要删除某个数据库 需要切换到该数据库 通过usedb进行切换

MongoDB创建集合与查看集合

  • 手动创建集合之不带关键字创建
  • 手动创建集合之带关键字创建集合

关键字参数用法:

整个集合空间大小 **5 B, **文档最大个数为 3个。 如果设置的大小小于256就默认是256自动创建集合。

  • 自动创建集合
    • MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。

MongoDB删除集合

MongoDB插入文档(简单的理解就是在集合/表中插入数据)

  • insert插入单条数据
  • insert插入多条数据
python 复制代码
for(i=3;i<10;i++)db.test01.insert({x:i})


  • 参数说明:
    • BulkWriteResult.writeErrors

文档数组,其中包含有关更新操作期间遇到的与写入问题无关的任何错误的信息。该writeErrors数组包含每个错误的写入操作的错误文档

复制代码
  - BulkWriteResult.writeConcernError

描述与写关注有关的错误的文档

复制代码
  - BulkWriteResult.nInserted

使用该Bulk.insert() 方法插入的文档数。对于通过带Bulk.find.upsert()选项的操作插入的文档

复制代码
  - BulkWriteResult.nUpserted

通过带Bulk.find.upsert()选项的操作插入的文档数 。

复制代码
  - BulkWriteResult.nMatched

选择用于更新或替换的现有文档数。如果更新/替换操作未更改现有文档

复制代码
  - BulkWriteResult.nModified

已更新或替换的现有文档数。如果更新/替换操作未更改现有文档

复制代码
  - BulkWriteResult.nRemoved

删除的文件数。

复制代码
  - BulkWriteResult.upserted

文档数组,包含有关通过带Bulk.find.upsert() 选项的操作插入的每个文档的信息。

MongoDB查询数据

python 复制代码
db.stu.insert([{"name" : "张三", "hometown" : "长沙", "age" : 20, "gender" : true },
{"name" : "老李", "hometown" : "广州", "age" : 18, "gender" : false },
{"name" : "王麻子", "hometown" : "北京", "age" : 18, "gender" : false },
{"name" : "刘六", "hometown" : "深圳", "age" : 40, "gender" : true },
{"name" : "jerry", "hometown" : "长沙", "age" : 16, "gender" : true },
{"name" : "小永", "hometown" : "广州 ", "age" : 45, "gender" : true },
{"name" : "老amy", "hometown" : "衡阳", "age" : 18, "gender" : true }])
  • db.stu.find() 查询数据/可以在括号里面精确查找
  • db.stu.find().pretty() 格式化文档打印
  • db.stu.find({name:'jerry'}).pretty() 精确查找并格式化打印
  • db.stu.findOne() 格式化打印第一条查询的数据
  • db.stu.find({age:18})
  • db.stu.findOne({age:18}) 把满足结果的第一条数据进行返回
  • db.stu.find({age:18,gender:true}) 在find中进行多条件查询
  • 查询之比较运算符
    • 等于:默认是等于判断,没有运算符
    • 小于:$lt
    • 小于等于:$lte
    • 大于:$gt
    • 大于等于:$gte
      • 查询年龄大于18的元素
        • db.stu.find({age:{$gt:18}})
python 复制代码
  - 查询年龄大于18的元素且hometown是长沙的元素
     - db.stu.find({age:{$gt:18},hometown:"长沙"})
  • 查询之范围运算符
    • 使用$in,$nin判断是否在某个范围内
      • 查询年龄为18和年龄28的学生
  • **查询之逻辑运算符 **
    • or: 使用$or,值为数组,数组中每个元素为json
    • 查询年龄大于18或者genderflase
      • db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})
  • 查询之自定义查询
    • 查询年龄大于18的学生
      • db.stu.find({$where:function(){return this.age>18}})

MongoDB操作查询数据

  • count 查出数据求总和 也可以精确查找想要的总和
  • limit 用于读取指定数量的文档
  • skip 用于跳过指定数量的文档
  • limitskip同时使用
  • 映射:指定返回的字段,如果为1则返回该字段 如果为0则除了该字段外所有字段返回。id如果没写会默认返回
  • id去除
  • 映射多个值
    • 比如只要年龄和性别不去除id
  • 排序
    • 升序
复制代码
  - 降序
复制代码
  - 根据find()精确查找然后进行排序

MongoDB更新文档

  • db.集合名称.update({query}, {update}, {multi: boolean})
    • 参数query:查询条件
    • 参数update:更新操作符
    • 参数multi:可选,默认是false,表示只更新找到的第一条数据,值为true表示把满足条件的数据全部更新
  • db.stu.update({name:'jerry'},{name:'杰瑞'}) 这种情况下 会改变name 但是其他的会被删除、
  • db.stu.update({name:'张三'},{$set:{name:'张三丰'}}) 这种情况下 会改变name并且其他的信息也不会变化
  • 更新多条 比如说将所有的gender变成0 此时会发现 如果没有gender这个属性会进行添加

MongoDB删除文档

  • remove() 方法的基本语法
    • db.collection.remove(<query>, <justOne> )
    • query : 删除的文档的条件。
    • justOne : 如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档
  • 删除符合条件的第一条数据
  • 删除符合条件的多条数据
  • 删除表/集合
    • 语法: db.集合名.drop()

MongoDB练习

测试数据:

python 复制代码
var persons = [{
        name:"jim",
        age:25,
        email:"[email protected]",
        c:89,m:96,e:87,
        country:"USA",
        books:["JS","C++","EXTJS","MONGODB"]
},
{
        name:"tom",
        age:25,
        email:"[email protected]",
        c:75,m:66,e:97,
        country:"USA",
        books:["PHP","JAVA","EXTJS","C++"]
},
{
        name:"lili",
        age:26,
        email:"[email protected]",
        c:75,m:63,e:97,
        country:"USA",
        books:["JS","JAVA","C#","MONGODB"]
},
{
        name:"zhangsan",
        age:27,
        email:"[email protected]",
        c:89,m:86,e:67,
        country:"China",
        books:["JS","JAVA","EXTJS","MONGODB"]
},
{
        name:"lisi",
        age:26,
        email:"[email protected]",
        c:53,m:96,e:83,
        country:"China",
        books:["JS","C#","PHP","MONGODB"]
},
{
        name:"wangwu",
        age:27,
        email:"[email protected]",
        c:45,m:65,e:99,
        country:"China",
        books:["JS","JAVA","C++","MONGODB"]
},
{
        name:"zhaoliu",
        age:27,
        email:"[email protected]",
        c:99,m:96,e:97,
        country:"China",
        books:["JS","JAVA","EXTJS","PHP"]
},
{
        name:"piaoyingjun",
        age:26,
        email:"[email protected]",
        c:39,m:54,e:53,
        country:"Korea",
        books:["JS","C#","EXTJS","MONGODB"]
},
{
        name:"lizhenxian",
        age:27,
        email:"[email protected]",
        c:35,m:56,e:47,
        country:"Korea",
        books:["JS","JAVA","EXTJS","MONGODB"]
},
{
        name:"lixiaoli",
        age:21,
        email:"[email protected]",
        c:36,m:86,e:32,
        country:"Korea",
        books:["JS","JAVA","PHP","MONGODB"]
},
{
        name:"zhangsuying",
        age:22,
        email:"[email protected]",
        c:45,m:63,e:77,
        country:"Korea",
        books:["JS","JAVA","C#","MONGODB"]
}]

for(var i = 0;i<persons.length;i++){
        db.persons.insert(persons[i])
}

var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
        obj = persons.next();
        print(obj.books.length)
}

练习问题:

python 复制代码
1.查询年龄大于25小于27的name,age
db.persons.find({age:{$gt:25,$lt:27}})

2.查询出不是美国的name
db.persons.find({country:{$ne:'USA'}})
db.persons.find({country:{$ne:'USA'}},{name:1})
db.persons.find({country:{$ne:'USA'}},{name:1,country:1})

3.查询国籍是中国或者美国的学生信息
db.persons.find({$or:[{country:'USA'},{country:'China'}]})
db.persons.find({$or:[{country:'USA'},{country:'China'}]},{country:1}) 数据有点多映射国家

4.查询语文成绩大于85或者英语成绩大于90的学生信息
db.persons.find({$or:[{c:{$gt:85}},{e:{$gt:90}}]})

5.查询出名字中存在"li"的学生信息
db.persons.find({name:/li/},{name:1})

6.查询喜欢看MONGODB和PHP的学生
db.persons.find({books:{$all:['MONGODB','PHP']}},{books:1})
db.persons.find({books:{$all:['MONGODB','PHP']}},{books:1,name:1})


7.查询第二本书是JAVA的学生信息
db.persons.find({},{books:1})
db.persons.find({'books.1':'JAVA'},{name:1,books:1})  'books.1'代表的是索引

8.查询喜欢的书数量是4本的学生
db.persons.find({books:{$size:4}},{books:1})

9.查询出persons中一共有多少国家分别是什么
db.persons.find({},{country:1})v
db.persons.distinct('country')

MongoDB创建索引

测试数据集

python 复制代码
for(i=0;i<100000;i++){db.test.insert({name:'test'+i,age:i})}

为什么要用到索引 ?

  • 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
  • 这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
  • 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

创建索引前:

python 复制代码
db.test.find({name:'test9999'})
db.test.find({name:'test9999'}).explain('executionStats') # 显示查询操作的详细信息

 "executionTimeMillis" : 39, 测试结果  "executionTimeMillis" : 37, 这个结果不唯一 

怎么去创建索引:

python 复制代码
db.test.ensureIndex({name:1})

创建索引后:

python 复制代码
db.test.find({name:'test9999'}).explain('executionStats')

"executionTimeMillis" : 6, 测试结果 
"executionTimeMillis" : 0,

查看所有的索引:

python 复制代码
db.test.getIndexes()
默认情况下_id是集合的索引

删除索引:

python 复制代码
语法:db.集合名.dropIndex({'索引名称':1})
db.test.dropIndex({name:1})
db.test.getIndexes()

注意:

在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

拓展: 关于mongodb资料参考:https://www.runoob.com/mongodb/mongodb-indexing.html

pythonMongoDB交互(掌握插入)

数据库的连接:

python 复制代码
from pymongo import MongoClient

# 连接
client = MongoClient()

MongoDB交互的增删改查:

python 复制代码
import pymongo
from pymongo import MongoClient


class Mongo_python:
    # 初始化方法
    def __init__(self, HOST, PORT):
        self.HOST = HOST
        self.PORT = PORT
        # 连接
        self.client = MongoClient(HOST, PORT)

    # 插入数据
    def insert_data(self):
        # 插入单条数据
        # self.client.school.teacher.insert_one({"name": "李璐2", "role": "兼职老师"})
        # 插入多条数据
        self.client.school.teacher.insert_many([{"name": "晨刚"}, {"name": "郭丽丽"}])

    # 查询数据
    def query_data(self):
        try:
            teachers = self.client.school.teacher.find()
            # print(list(teachers),type(teachers))
            # for one in teachers:
            #     print("查找多条数据:", one["_id"], one["name"])

            teacher = self.client.school.teacher.find_one({"name": "李璐2"})
            print("查找单条数据:", teacher["_id"], teacher["name"])
        except Exception as e:
            print(e)

    # 修改数据
    def set_data(self):
        # 修改多条数据
        # self.client.school.teacher.update_many(
        #     {}, {"$set": {"role": "班主任11111"}}
        #
        # )
        # 修改单条数据
        # self.client.school.teacher.update_one({"name": "晨刚"}, {"$set": {"sex": "女"}})
        # push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
        self.client.school.teacher.update_one({"name": "晨刚"}, {"$push": {"sdarole": "年级主任"}})

    # 删除数据
    def delete_data(self):
        try:
            # 删除单条数据
            # self.client.school.teacher.delete_one({"name": "晨刚"})
            # 删除多条数据
            # 第一个参数是一个查询对象,用于定义要删除的文档
           query = {"name": '李璐2'}
           self.client.school.teacher.delete_many(query)
        except Exception as e:
            print(e)


if __name__ == '__main__':
    mg = Mongo_python('localhost', 27017)
    # mg.insert_data()
    # mg.query_data()
    # mg.set_data()
    mg.delete_data()
相关推荐
bing_1582 分钟前
在 Spring Boot 项目中,如何进行高效的数据库 Schema 设计?
数据库·spring boot·后端·数据库schema设计
Tanecious.6 分钟前
机器视觉--Python补充知识
android·开发语言·python
听雪楼主.19 分钟前
Oracle补丁安装工具opatch更新报错处理
数据库·oracle
不吃元西19 分钟前
对于客户端数据存储方案——SQLite的思考
数据库·sqlite
rgb0f022 分钟前
MySQL视图相关
数据库·mysql·oracle
编程、小哥哥25 分钟前
oracle值sql记录
数据库·sql·oracle
三千花灯31 分钟前
jmeter提取返回值到文件
数据库·jmeter
萧离1951 小时前
超细的Linux安装minio教学
数据库
大模型真好玩1 小时前
一文带你了解RAG核心原理!不再只是文档的搬运工
人工智能·python·ai编程
小吕学编程1 小时前
基于Canal+Spring Boot+Kafka的MySQL数据变更实时监听实战指南
数据库·后端·mysql·spring·kafka