SPSS+AMOS数据分析案例教程-关于中介模
SPSS视频教程内容目录和跳转链接
SPSS+AMOS数据分析案例教程-关于中介模
SPSS视频教程内容目录和跳转链接
R语言快速入门视频教程
Python智联招聘数据分析
LCA潜在类别分析和Mplus应用
Amos结构方程模型数据分析入门教程
倒U关系回归分析中介效应和调节效应分析SPSS视频教程

python+mongodb生态坏境部署和上手体验

在B站@mlln-cn, 我就能回答你的问题奥!

文章目录
  1. 1. 系统环境
  2. 2. 安装mongodb
  3. 3. 使用compass创建数据库和文档集
  4. 4. 安装和使用PyMongo
  5. 5. MongoEngine面向对象的数据库操作
    1. 5.1. 安装MongoEngine
    2. 5.2. 定义文档类
    3. 5.3. 在类中添加自己的方法
    4. 5.4. 文档的互相引用
  6. 6. 总结

Python是一种功能强大的编程语言,用于开发社区中的许多不同类型的应用程序。许多人都知道它是一种灵活的语言,可以处理任何任务。

那么,如果我们复杂的Python应用程序需要一个与语言本身一样灵活的数据库呢?

这就是NoSQL,特别是MongoDB的用武之地。

在这篇文章里, 我系统的介绍了mongodb的安装部署, 可视化管理, python相关库的安装和基本用法。

系统环境

  • windows10
  • python3.6

安装mongodb

  • mongodb安装完成以后, 你会得到一个compass, 它是用于可视化管理数据库的, 并且在桌面上已经为你创建好了一个compass快捷方式, 打开mongodb compass,
    你会看到一个登录界面, 这个界面的默认参数都不要改, 直接点击connect就可以链接上你本地的数据库:

使用compass创建数据库和文档集

  • 使用compass创建一个名为ip_poll的数据库

  • 点击创建

  • 填写数据库名称, 并且你需要填写一个文档集名称, 只有填写了文档集名称才能为你创建数据库, 因为本质上, mongodb中的数据库只是一个”分组”的概念, 也就是文档集的分组, 如果没有文档集, 也就没有所谓的组。
  • 创建完成以后, 你就可以看到, 界面的左侧是数据库列表, 列表展开就是文档集列表, 界面右侧可以看到具体信息:

安装和使用PyMongo

Pymongo是mongodb开发团队为python提供的sdk, 所以为了在python中使用mongo, 我们最好是从pymongo开始学习。

  • 通过pip安装PyMongo
1
!pip install pymongo
输出(stream):
Collecting pymongo Downloading https://files.pythonhosted.org/packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl (321kB) Installing collected packages: pymongo Successfully installed pymongo-3.8.0
输出(stream):
Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 11002] getaddrinfo failed',)': /packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 11002] getaddrinfo failed',)': /packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 11002] getaddrinfo failed',)': /packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 11002] getaddrinfo failed',)': /packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 11001] getaddrinfo failed',)': /packages/c7/af/37efccd56d4d2498240eed09587394e27c5900238f3dc46715844385c202/pymongo-3.8.0-cp36-cp36m-win_amd64.whl You are using pip version 19.0.3, however version 19.1.1 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command.
  • 快速入门pymongo
1
2
3
4
5
# 引入客户端类
from pymongo import MongoClient
# 实例化, 这个过程就是与本地的mongodb建立链接
# 服务器地址是"localhost", 端口是默认的"27017"
client = MongoClient()

当然你还可以使用下面两种可选方式建立链接, 效果和上面是一样的:

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

获取数据库对象, 比如我们上面创建了一个”ip_pool”数据库:

1
2
ipp = client.ip_pool
ipp
输出(plain):
Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'ip_pool')

或者你可以使用类似字典的方式获取数据库实例:

1
2
ipp = client['ip_pool']
ipp
输出(plain):
Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'ip_pool')

获取文档集(类似于mysql中的表的概念):

1
2
ips = ipp.ips
ips
输出(plain):
Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'ip_pool'), 'ips')

下面演示一下基本的数据库的增改查删:

先插入一条记录:

1
2
3
4
5
6
7
8
9
# 插入一条记录

ip = {
'address': '17.2.3.4',
'location': '北京 西城区',
}

result = ips.insert_one(ip)
print('result:', result)
输出(stream):
result:

当然我们可以一次性插入多条:

1
2
3
4
5
6
7
8
9
10
11
12
13
ip1 = {
'address': '17.2.3.40',
'location': '北京 西城区',
}

ip2 = {
'address': '17.2.3.41',
'location': '北京 西城区',
}


result = ips.insert_many([ip1, ip2])
print('inserted ips:', result.inserted_ids)
输出(stream):
inserted ips: [ObjectId('5d09952dc7080f39b801c1bb'), ObjectId('5d09952dc7080f39b801c1bc')]

下面插叙一下数据库中的ip:

1
2
3
# 找出一条ip

ips.find_one()
输出(plain):
{'_id': ObjectId('5d0993e1c7080f39b801c1b9'),
'address': '17.2.3.4',
'location': '北京 西城区'}

找出北京西城区的一个ip:

1
ips.find_one({'location': '北京 西城区'})
输出(plain):
{'_id': ObjectId('5d0993e1c7080f39b801c1b9'),
'address': '17.2.3.4',
'location': '北京 西城区'}

找出北京西城区的所有ip:

1
ips.find({'location': '北京 西城区'})
输出(plain):

上面输出的结果可以看出, 当查询多条文档的时候, 我们并不能直接得到数据, 我们只是得到一个指针对象, 为了得到所有的数据, 我们需要循环:

1
2
for ip in ips.find({'location': '北京 西城区'}):
print(ip)
输出(stream):
{'_id': ObjectId('5d0993e1c7080f39b801c1b9'), 'address': '17.2.3.4', 'location': '北京 西城区'} {'_id': ObjectId('5d09952dc7080f39b801c1bb'), 'address': '17.2.3.40', 'location': '北京 西城区'} {'_id': ObjectId('5d09952dc7080f39b801c1bc'), 'address': '17.2.3.41', 'location': '北京 西城区'}

删除一条文档:

1
ips.delete_one({})
输出(plain):
1
ips.update_one({}, {'$set': {'ip': '1.1.1.1'}})
输出(plain):

查看更改后的数据:

1
2
for ip in ips.find({'location': '北京 西城区'}):
print(ip)
输出(stream):
{'_id': ObjectId('5d09952dc7080f39b801c1bb'), 'address': '17.2.3.40', 'location': '北京 西城区', 'ip': '1.1.1.1'} {'_id': ObjectId('5d09952dc7080f39b801c1bc'), 'address': '17.2.3.41', 'location': '北京 西城区'}

MongoEngine面向对象的数据库操作

虽然PyMongo非常易于使用,并且总体上是一个很棒的库,但对于许多项目而言,它可能有点太低级了。换句话说,你必须编写很多自己的代码来实现保存/检索和删除对象。

一个在PyMongo之上提供更高抽象的库是MongoEngine。 MongoEngine是一个对象文档映射器(ODM),它大致相当于基于SQL的对象关系映射器(ORM)。 MongoEngine提供的抽象是基于类的,因此你创建的所有模型都是类。

虽然有很多Python库可以帮助你使用MongoDB,但MongoEngine是最好的之一,因为它具有很好的功能/灵活性和社区支持。

安装MongoEngine

1
!pip install mongoengine
输出(stream):
Collecting mongoengine Downloading https://files.pythonhosted.org/packages/4d/25/9af6b83b847f445303ec8fda97e0ac01ba6fa4a11ee4f04d8397369cfc77/mongoengine-0.18.0.tar.gz (152kB) Requirement already satisfied: pymongo>=3.4 in d:\venv\.common\lib\site-packages (from mongoengine) (3.8.0) Requirement already satisfied: six in d:\venv\.common\lib\site-packages (from mongoengine) (1.12.0) Building wheels for collected packages: mongoengine Building wheel for mongoengine (setup.py): started Building wheel for mongoengine (setup.py): finished with status 'done' Stored in directory: C:\Users\syd\AppData\Local\pip\Cache\wheels\25\8f\00\7c0af82b6a41019b733502173dc00934ef68e5c6f57d494a6c Successfully built mongoengine Installing collected packages: mongoengine Successfully installed mongoengine-0.18.0
输出(stream):
You are using pip version 19.0.3, however version 19.1.1 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command.

定义文档类

要设置我们的文档对象,我们需要定义文档对象所需的数据。与许多其他ORM类似,我们将通过继承Document类并提供我们想要的数据类型来实现:

1
2
3
4
5
from mongoengine import *

class Ip(Document):
address = StringField(required=True)
location = StringField(required=False, max_length=50)

如果你直接去插入一个文档的话, 机会出现问题, 因为我们还没有与数据库建立连接:

1
2
ip = Ip(address='23.4.5.6', location='河北省')
ip.save() # 相当于insert_one操作
---------------------------------------------------------------------------

MongoEngineConnectionError                Traceback (most recent call last)

<ipython-input-26-40c2d38cec6d> in <module>
      1 ip = Ip(address='23.4.5.6', location='河北省')
----> 2 ip.save() # 相当于insert_one操作


d:\venv\.common\lib\site-packages\mongoengine\document.py in save(self, force_insert, validate, clean, write_concern, cascade, cascade_kwargs, _refs, save_condition, signal_kwargs, **kwargs)
    376 
    377         if self._meta.get('auto_create_index', True):
--> 378             self.ensure_indexes()
    379 
    380         try:


d:\venv\.common\lib\site-packages\mongoengine\document.py in ensure_indexes(cls)
    852             warnings.warn(msg, DeprecationWarning)
    853 
--> 854         collection = cls._get_collection()
    855         # 746: when connection is via mongos, the read preference is not necessarily an indication that
    856         # this code runs on a secondary


d:\venv\.common\lib\site-packages\mongoengine\document.py in _get_collection(cls)
    191                 cls._collection = cls._get_capped_collection()
    192             else:
--> 193                 db = cls._get_db()
    194                 collection_name = cls._get_collection_name()
    195                 cls._collection = db[collection_name]


d:\venv\.common\lib\site-packages\mongoengine\document.py in _get_db(cls)
    174     def _get_db(cls):
    175         """Some Model using other db_alias"""
--> 176         return get_db(cls._meta.get('db_alias', DEFAULT_CONNECTION_NAME))
    177 
    178     @classmethod


d:\venv\.common\lib\site-packages\mongoengine\connection.py in get_db(alias, reconnect)
    323 
    324     if alias not in _dbs:
--> 325         conn = get_connection(alias)
    326         conn_settings = _connection_settings[alias]
    327         db = conn[conn_settings['name']]


d:\venv\.common\lib\site-packages\mongoengine\connection.py in get_connection(alias, reconnect)
    233         else:
    234             msg = 'Connection with alias "%s" has not been defined' % alias
--> 235         raise MongoEngineConnectionError(msg)
    236 
    237     def _clean_settings(settings_dict):


MongoEngineConnectionError: You have not defined a default connection

我们需要先创建一个默认连接:

1
connect('ip_pool', host='localhost', port=27017)
输出(plain):
MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True, read_preference=Primary())

再去执行插入操作:

1
2
ip = Ip(address='23.4.5.6', location='河北省')
ip.save() # 相当于insert_one操作
输出(plain):

有关save方法的一些注意事项:

调用.save()时,PyMongo将执行验证。这意味着它将根据你在类中声明的数据格式检查要保存的数据。如果违反了数据格式(或约束),则抛出异常并且不保存数据。
由于Mongo不支持真正的transaction,因此无法像在SQL数据库中那样“回滚”.save()。

在类中添加自己的方法

面向对象的好处就是, 把各种方法聚合到不同的类上, 同样MongoEngine也支持这样做:

1
2
3
4
5
6
7
class Ip(Document):
address = StringField(required=True)
location = StringField(required=False, max_length=50)

@queryset_manager
def beijing_ips(clazz, queryset):
return queryset.filter(location='北京 西城区')

文档的互相引用

类似于关系型数据库中的外键, 你可以使用ReferenceField来声明一个外键:

1
2
3
4
5
6
7
class Supplier(Document):
name = StringField()

class Ip(Document):
address = StringField(required=True)
location = StringField(required=False, max_length=50)
sup = ReferenceField(Supplier)

总结

由于Python是一种高级/高度可扩展的现代语言,它需要一个能够保持其潜力的数据库(和驱动程序),这就是为什么MongoDB非常适合的原因。

我们在本文中看到了如何利用MongoDB的优势来构建高度灵活且可扩展的应用程序。

持续关注mlln.cn, 我会经常更新有关python+mongodb的技术点。

注意
本文由jupyter notebook转换而来, 您可以在这里下载notebook
统计咨询请加QQ 2726725926, 微信 mllncn, SPSS统计咨询是收费的
微博上@mlln-cn可以向我免费题问
请记住我的网址: mlln.cn 或者 jupyter.cn

赞助

持续创造有价值的内容, 我需要你的帮助