10高效存储MongoDB

当我们成功提取了数据之后,该往哪里存放呢?

用文本文件当然是可以的,但文本存储不方便检索

有没有既方便存,又方便检索的存储方式呢?——MongoDB

MongoDB是由C++语言编写的非关系型数据库

是一个基于分布式文件存储的开源数据库系统

其内容存储形式类似JSON对象,它的字段值可以包含其他文档、数组、文档数组

为什么不用MySQL?

mysql对于一些结构化或嵌套类型的数据存储不太方便,而且需要额外维护字段信息,相对麻烦

MongoDB适合存储这类数据

准备工作

开始之前,请确保你已经安装好了MongoDB并启动了其服务,同时安装好了Python的PyMongo库

MongoDB安装教程:https://www.cnblogs.com/TM0831/p/10606624.html

安装好之后,我们需要把MongoDB服务启动起来

  • 注意:这里我们为了学习,仅使用MongoDB最基本的单机版,MongoDB还有主从复制、副本集、分片集群架构,可用性可靠性更好,如有需要可以自行搭建相应的集群进行使用

启动完成之后,它会默认在本地localhost的27017端口上运行

接下来我们需要安装PyMongo库,它是Python用来操作MongoDB的第三方库

pip install pymongo

连接MongoDB

连接MongoDB时,我们需要使用PyMongo库里面的MongoClient

一般来说,我们需要向其传入MongoDB的IP及端口

其中第一个参数为地址host,第二个参数为端口port(默认27017)

import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)

这样就可以创建MongoDB的连接对象了

MongoClient的第一个参数host还可以直接传入MongoDB的连接字符串,它以mongodb开头

client = MongoClient('mongodb://localhost:27017/')

也可以达到同样的连接效果

指定数据库

MongoDB中可以建立多个数据库

我们需要指定操作其中一个数据库,以test数据库作为指定使用的例子

db = client.test

这里调用client的test属性即可返回test数据库

还有一种等价的指定方式

db = client['test']

指定集合

MongoDB的每个数据库中包含了许多集合**(collection)**

它们类似于关系型数据库(mysql、SQL Server…)中的表

我们指定一个名称为students的集合,与指定数据库类似,指定集合也有两种方式

collection = db.students

或者

collection = db['students']

这样我们便声明了一个Collection对象

插入数据

我们对students这个集合新建一条学生数据,这条数据以字典形式表示

student = {'id': '20170101','name': 'Jordan','age': 20,'gender': 'male'
}

数据制定了学生的学好、姓名、年龄和性别。

接下来,我们直接调用 collection的insert方法即可插入数据

result = collection.insert(student)
print(result)

在MongoDB中,每条数据其实都有一个_id属性来唯一标识

如果没有显式(清楚且明确的指定了实现内容) 指明该属性,MongoDB会自动产生一个ObjectId类型的_id属性

insert()方法会在执行后返回_id值


我们也可以同时插入多条数据,只需要以列表形式传递即可

student1 = {'id': '20170102','name': 'Leon','age': 22,'gender': 'male'
}student2 = {'id': '20170203','name': 'Mike','age': 21,'gender': 'male'
}
result = collection.insert([student1,student2])
print(result)

返回结果是对应的_id的集合

DeprecationWarning: insert is deprecated. Use insert_one or insert_many instead

实际上,在PyMongo中,官方已经不推荐使用insert方法了

目前官方推进使用insert_one 和 insert_many方法来分别插入单条记录和多条记录

student = {'id': '20170204','name': 'Tom','age': 25,'gender': 'male'
}result = collection.insert_one(student)
print(result)
print(result.inserted_id)

与insert方法不同,这次返回的是InsertOneResult对象

我们可以调用其inserted_id属性获取_id


对于insert_many方法,我们可以将数据以列表形式传递

student1 = {'id': '20170105','name': 'Jack','age': 20,'gender': 'male'
}student2 = {'id': '20170206','name': 'Xiaoming','age': 21,'gender': 'male'
}result = collection.insert_many([student1,student2])
print(result)
print(result.inserted_ids)

该方法返回的类型是InsertManyResult,调用inserted_ids属性可以获取插入数据的_id列表


查询

插入数据后,我们可以利用find_one或find方法进行查询

  • find_one查询得到的是单个结果
  • find则返回一个生成器对象
result = collection.find_one({'name':'Leon'})
print(type(result))
print(result)

我们查询name为Leon的数据,它的返回结果是字典类型

可以发现,它多了_id属性,这就是MongoDB在插入过程中自动添加的

我们还可以根据ObjectId来查询,此时需要调用bson库里面的objectid

from bson.objectid import ObjectIdresult = collection.find_one({'_id':ObjectId('602e2e28df03b698a534a0b2')})

如果查询结果不存在,则会返回None

对于多条数据的查询,我们可以使用find方法。

例如,查找年龄为20的数据

results = collection.find({'age':20})
print(results)
for result in results:print(result)

返回Cursor类型,它相当于一个生成器,我们需要遍历获取的所有结果,其中每个结果都是字典类型

查询年龄大于20的数据

results = collection.find({'age':{'$gt':20}})

这里查询条件的键值已经不是单纯的数字了,而是一个字典,其键名为比较符号**$gt**,意思是大于,键值为20

比较符号归纳如下

还可以进行正则匹配查询,例如,查询名字以M开头的学生数据

results = collection.find({'name':{'$regex':'^M.*'}})

使用$regex来指定正则匹配,^M.*代表以M开头的正则表达式

功能符号归类如下

这些操作的更详细用法,参考https://docs.mongodb.com/manual/reference/operator/query/

计数

要统计查询结果有多少条数据,可以调用count方法

我们统计所有数据条数

count = collection.find().count()
print(count)

还可以统计符合某个条件的数据

count = collection.find({'age':21}).count()
print(count)

排序

可以调用sort方法,并在其中传入排序的字段及升降序标志

results = collection.find().sort('name',pymongo.ASCENDING)
print([result['name']for result in results])

这里我们调用pymongo.ASCENDING指定升序,如果要降序排列,可以传入pymongo.DESCENDING

偏移

某些情况下,我们可能只需要取某几个元素,利用skip方法偏移几个位置,比如偏移2,就代表忽略前两个元素,得到第3个及以后的元素

results = collection.find().sort('name',pymongo.ASCENDING).skip(2)
print([result['name']for result in results])

我们还可以用limit方法指定要取的结果个数

results = collection.find().sort('name',pymongo.ASCENDING).skip(2).limit(2)
print([result['name']for result in results])

加了limit方法,限制之后,就会截取两个结果返回

  • 值得注意的是,在数据量非常庞大的时候,比如在查询千万、亿级别的数据库时,最好不要使用大的偏移量,这样很可能导致内存溢出

  • 此时可以使用如下操作来查询

    from bson.objectid import ObjectId

    collection.find({'_id:{'$gt':ObjectId('602e2e28df03b698a534a0b2')}'})

这时需要记录好上次查询的_id

更新

对于数据更新,我们可以使用update方法,指定更新的条件和更新后的数据即可

condition = {'name':'Mike'}
student = collection.find_one(condition)
student['age']= 25
result = collection.update(condition,student)
print(result)

我们要更新name为Mike的数据的年龄:首先指定查询条件,然后将数据查询出来,修改年龄后调用update方法将原条件和修改后的数据传入

返回结果是字典形式,ok代表执行成功,nModified代表影响的数据条数


我们也可以使用**$set操作符**对数据进行更新

result = collection.update(condition,{'$set':student})

这样可以只更新student字典内存在的字段

如果原先还有其他字段,则不会更新,也不会删除

而如果不用$set的话,则会把之前的数据全部用student字典替换

如果原本存在其他字段,则会被删除


另外,update方法也是官方不推荐使用的方法。推荐使用update_one和update_many方法

用法更加严格,它们的第2个参数需要使用$类型操作符作为字典的键名

condition = {'name':'Mike'}
student = collection.find_one(condition)
student['age'] = 26
result = collection.update_one(condition,{'$set':student})
print(result)
print(result.matched_count,result.modified_count)

调用update_one方法,使得第2个参数不能再直接传入修改后的字典,而是需要使用{’$set’:student}这样的形式

其返回结果是UpdateResult类型。然后分别调用matched_count和modified_count属性,可以获得匹配的数据条数和影响的数据条数

再看一个例子

condition = {'age':{'$gt':20}}
result = collection.update_one(condition,{'$inc':{'age':1}})
print(result)
print(result.matched_count,result.modified_count)

这里指定查询条件为年龄大于20,然后更新条件为

{’$inc’:{‘age’:1}},表示年龄加1,执行之后会将第一条符合条件的数据年龄加1

匹配条数为1条,影响条数也为1条

如果调用update_many方法,则会将所有符合条件的数据都更新

condition = {'age':{'$gt':20}}
result = collection.update_many(condition,{'$inc':{'age':1}})
print(result)
print(result.matched_count,result.modified_count)

这时所有匹配到的数据都会被更新

删除

删除操作比较简单,直接调用remove方法指定删除的条件即可,此时符合条件的数据均会被删除

result = collection.remove({'name':'Mike'})
print(result)

这里官方依然推荐两个新方法——delete_one、delete_many

result = collection.delete_one({'name':'Xiaoming'})
print(result)
print(result.deleted_count)
result = collection.delete_many({'age':{'$gt':25}})
print(result.deleted_count)

delete_one即删除第一个符合条件的数据,delete_many即删除所有符合条件的数据

它们返回结果都是DeleteResult类型,可以调用deleted_count属性获取删除的数据条数

其他操作

PyMongo还提供了一些组合方法

  • find_one_and_delete 查找后删除

  • find_one_and_replace 查找后替换

  • find_one_and_update 查找后更新

还可以对索引进行操作

create_index 、 create_indexes 、drop_index等

PyMongo还提供了一些组合方法

  • find_one_and_delete 查找后删除

  • find_one_and_replace 查找后替换

  • find_one_and_update 查找后更新

还可以对索引进行操作

create_index 、 create_indexes 、drop_index等

PyMongo的详细用法,参见官方文档http://api.mongodb.com/python/current/api/pymongo/collection.html

数据库和集合本身的操作,参见官方文档http://api.mongodb.com/python/current/api/pymongo/

沭阳学爬虫10高效存储MongoDB相关推荐

  1. 第10讲:高效存储 MongoDB 的用法

    上节课我们学习了如何用 pyquery 提取 HTML 中的信息,但是当我们成功提取了数据之后,该往哪里存放呢? 用文本文件当然是可以的,但文本存储不方便检索.有没有既方便存,又方便检索的存储方式呢? ...

  2. 沭阳学爬虫03爬虫基本原理

    爬虫基本原理 爬虫,就是获取网页并提取和保存信息的自动化程序 获取网页 爬虫首先要做的工作就是获取网页,就是获取网页的源代码 源代码里包含了网页的部分有用信息,所以只要把源代码获取下来,就可以从中提取 ...

  3. 沭阳学爬虫01HTTP基本原理

    崔大的爬虫课,自己抄书式的笔记,以便复习,也希望能给志同道合的朋友提供小小的帮助 01|掌握HTTP基本原理 URI和URL URI (Uniform Resource Identifier), 统一 ...

  4. 一起学爬虫(Python) — 10

    一起学爬虫(Python) - 19 年轻人,进来学自动化 高效爬取美丽的图片 任务目标 任务流程 step1:复制 step2:粘贴 step3:重学异步 什么是异步 勤奋的小明 理解小明 理解~~ ...

  5. 盲沟低比?不不不,是芒果的笔,今天学一下分布式文件存储数据库MongoDB。

    老样子先上图,上一篇NOSQL有大佬说要把首图的数据库全部学习了,今天特意只上了一张小图,一个就够了! 文章目录 前言 一.MongoDB 历史 二.MongoDB 支持语言 三.MongoDB 与关 ...

  6. Python爬取豆瓣音乐存储MongoDB数据库(Python爬虫实战1)

    Python爬取豆瓣音乐存储MongoDB数据库(Python爬虫实战1) 1.  爬虫设计的技术 1)数据获取,通过http获取网站的数据,如urllib,urllib2,requests等模块: ...

  7. 这年头学爬虫还就得会点 scrapy 框架

    Hello,我是 Alex 007,为啥是007呢?因为叫 Alex 的人太多了,再加上每天007的生活,Alex 007就诞生了. 这几天一直在练车,只能在中间休息的时候写一写博客,可怜去年报的名到 ...

  8. 【小白学爬虫连载(1)】-爬虫框架简介

    欢迎大家关注公众号[哈希大数据] [小白学爬虫连载(1)]-爬虫框架简介 [小白学爬虫连载(2)]--Requests库介绍 [小白学爬虫连载(3)]--正则表达式详细介绍 [小白学爬虫连载(4)]- ...

  9. 一起学爬虫(Python) — 08

    一起学爬虫(Python) - 19 年轻人,进来学自动化 今天我又回来啦 聊一聊 首先 一心多用 async 后面跟方法 是今天才到的200赞哦!所以今天就开始更新啦,其实有点头疼该写什么了,犹豫是 ...

最新文章

  1. 有趣的计算机课的作文,有趣的电脑课作文500字
  2. 《阿里云前端技术周刊》第五期
  3. 使用Vim+Ctags+Cscope阅读源代码
  4. 取IDE当前文档所在项目的目录[vs.net2008]
  5. C#创建Access
  6. android listview添加数据_Android面经分享,失业两个月,五一节前拿到offer
  7. Swift iOS : 内存管理
  8. 【leetcode】【动态规划】最长回文子序列
  9. css 倒三角_改善CSS的10种最佳做法,帮助你从样式中获得最大的收益。
  10. hdoj--5620--KK's Steel(斐波那契数)
  11. MySQL 基础系列篇
  12. 无线通信网络学习之LTE网络架构篇(20141208)
  13. 微信小程序布局理解——flex、block、inline
  14. SpringMVC工作原理(含案例图解)
  15. 深度学习阅读导航 | 02 Faster R-CNN:基于RPN的实时目标检测
  16. 计算机管理储存u盘无法使用,小编教你无法格式化u盘怎么解决
  17. 什么是股票量化交易软件?
  18. java 地铁线路_个人项目-地铁出行路线规划(Java代码实现)
  19. httpclient登录百度https登录地址
  20. php的cmf框架哪个比较好,不要用这个CMF ThinkCMF内容管理框架,做最简约的ThinkPHP开源软件...

热门文章

  1. 微服务实施笔记(四)——部署服务发现
  2. Ps的动感模糊和扭曲效果
  3. 微信抢红包的方案_微信抢红包怎样才能抢到最大的告诉你一个方法
  4. 【Arduino】关于使用USB-ISP烧入bootloader的一些记录
  5. 2019前端面试题记录(杂文)
  6. 数据库中几个基本概念 主码 外码
  7. 云天视界传媒浅谈无人机航拍技巧
  8. 银河土星_设计师来自土星,开发人员来自木星:或者,为什么沟通很重要
  9. 消防基础知识——燃烧与火灾
  10. 线上拼团活动方案怎么制作设计?