MongoDB学习笔记:Python 操作MongoDB

时间:2021-07-11 08:52:10

MongoDB学习笔记:Python 操作MongoDB

Pymongo 安装

安装pymongo
pip install pymongo
PyMongo是驱动程序,使python程序能够使用Mongodb数据库,使用python编写而成;

数据库相关操作

连接及创建数据库

import pymongo

connect = pymongo.MongoClient("mongodb://localhost:27017/")

mydb = connect ["test"]

注意:在 MongoDB 中,初次创建数据库,数据库在获取内容之前不会真正创建的!

在实际创建数据库(和集合)之前,MongoDB 会一直等待您创建至少有一个文档(记录)的集合(表)。

连接及查看数据库

from pymongo import MongoClient
connect = MongoClient(host='localhost', port=27017, username="root", password="123456")
#connect = MongoClient('mongodb://localhost:27017/', username="root", password="123456")
print(connect.list_database_names())

 单例模式封装链接

注意:

mongodb的数据库连接池的问题,在创建MongoClient 的时候就已经创建了一个连接池,每一个操作(增删改查等)都会获取一个连接,执行操作后释放连接。

而连接池是不需要我们及时关闭的,我们可以在程序的生命周期中维护一个这样的单例,至于从连接池中拿出的连接,我们也不需要自行关闭。

所以这里self.db实例其实已经是一个现成的连接池了,而且线程安全。内置的连接池默认初始了100个连接,每一个操作(增删改查等)都会获取一个连接,执行操作后释放连接。

最大连接限制最大连接数限制,默认值为 1000000。

如果你需要为进程中支持大量并发MongoDB操作,请增加maxPoolSize

client = MongoClient(host, port, maxPoolSize=200)

或使其不受限制:

client = MongoClient(host, port, maxPoolSize=None)

一旦池达到最大大小,其他线程就必须等待套接字可用。PyMongo并不限制等待套接字可用的线程数,应用程序有责任在负载高峰期间将其线程池的大小限制为绑定队列。除非waitQueueTimeoutMS定义,否则允许线程等待任何时间长度 :

client = MongoClient(host, port, waitQueueTimeoutMS=100)

等待套接字等待时间超过100ms(在此示例中)的线程引发 ConnectionFailure。如果限制负载高峰期间的操作持续时间比完成每个操作更为重要,请使用此选项。

另外不要为了每个操作都去创建一个新的MongoClient实例,这是非常低效的。

from pymongo import MongoClient

class MongoDBClient(object):
# 饿汉式 单例模式
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(MongoDBClient, cls).__new__(cls)
return cls.instance
# 代理ip Redis 连接池
def __init__(self):
uri = 'mongodb://账号:密码@128.777.244.19:27017/admin'
self.mgdb = MongoClient(uri, connect=False, maxPoolSize=2000) def getMongoClient(self):
return self.mgdb

集合相关操作

检查 "customers" 集合是否存在

from pymongo import MongoClient
connect = MongoClient(host='localhost', port=27017, username="root", password="123456")
#connect = MongoClient('mongodb://localhost:27017/', username="root", password="123456")
collist = mydb.list_collection_names()
if "customers" in collist:
print("The collection exists.")

创建名为 "customers" 的集合

import pymongo

connect = pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["test"]
mycol = test_db["customers"]

获取数据库及集合实例

from pymongo import MongoClient
connect = MongoClient(host='localhost', port=27017, username="root", password="123456")
获取数据库实例
test_db = connect['test']
获取collection实例
collection = test_db['students']

删除数据库下的集合

使用drop() 方法删除在 MongoDB 中的集合。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] mycol.drop()

注意:如果成功删除集合,则 drop() 方法返回 true,如果集合不存在则返回 false。

文档相关操作

插入文档

在集合中插入单个文档

insert_one() 方法的第一个参数是字典,其中包含希望插入文档中的每个字段名称和值。

from pymongo import MongoClient
from datetime import datetime connect = MongoClient(host='localhost', port=27017, username="root", password="123456",)
# 获取db
test_db = connect['test']
# 获取collection
collection = test_db['students']
# 构建document
document = {"author": "Mike", "text": "My first blog post!", "tags": ["mongodb", "python", "pymongo"], "date": datetime.now()}
# 插入document
one_insert = collection.insert_one(document=document)
print(one_insert.inserted_id)

注意:insert_one() 方法返回 InsertOneResult 对象,该对象拥有属性 inserted_id,用于保存插入文档的 id。

在集合中插入多个文档

insert_many() 方法的第一个参数是包含字典的列表,其中包含要插入的数据:

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] mylist = [
{ "name": "Amy", "address": "Apple st 652"},
{ "name": "Hannah", "address": "Mountain 21"},
{ "name": "Michael", "address": "Valley 345"},
{ "name": "Sandy", "address": "Ocean blvd 2"},
{ "name": "Betty", "address": "Green Grass 1"},
{ "name": "Richard", "address": "Sky st 331"},
{ "name": "Susan", "address": "One way 98"},
{ "name": "Vicky", "address": "Yellow Garden 2"},
{ "name": "Ben", "address": "Park Lane 38"},
{ "name": "William", "address": "Central st 954"},
{ "name": "Chuck", "address": "Main Road 989"},
{ "name": "Viola", "address": "Sideway 1633"}
] x = mycol.insert_many(mylist) # 打印被插入文档的 _id 值列表:
print(x.inserted_ids)

注意:insert_many() 方法返回 InsertManyResult 对象,该对象拥有属性 inserted_ids(id列表),用于保存被插入文档的 id。

插入带有指定 ID 的多个文档

如果您不希望 MongoDB 为您的文档分配唯一 id,则可以在插入文档时指定 _id 字段。

请记住,值必须是唯一的。两个文件不能有相同的 _id。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] mylist = [
{ "_id": 1, "name": "John", "address": "Highway 37"},
{ "_id": 2, "name": "Peter", "address": "Lowstreet 27"},
{ "_id": 3, "name": "Amy", "address": "Apple st 652"},
{ "_id": 4, "name": "Hannah", "address": "Mountain 21"},
{ "_id": 5, "name": "Michael", "address": "Valley 345"},
{ "_id": 6, "name": "Sandy", "address": "Ocean blvd 2"},
{ "_id": 7, "name": "Betty", "address": "Green Grass 1"},
{ "_id": 8, "name": "Richard", "address": "Sky st 331"},
{ "_id": 9, "name": "Susan", "address": "One way 98"},
{ "_id": 10, "name": "Vicky", "address": "Yellow Garden 2"},
{ "_id": 11, "name": "Ben", "address": "Park Lane 38"},
{ "_id": 12, "name": "William", "address": "Central st 954"},
{ "_id": 13, "name": "Chuck", "address": "Main Road 989"},
{ "_id": 14, "name": "Viola", "address": "Sideway 1633"}
] x = mycol.insert_many(mylist) # 打印被插入文档的 _id 值列表:
print(x.inserted_ids)

更新集合

更新集合中的单个文档

update_one() 方法来更新 MongoDB 集合中的文档。

第一个参数是 query 对象,用于定义要更新的文档。

第二个参数是定义文档新值的对象。

注意:如果查询找到多个记录,则仅更新第一个匹配项。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] myquery = { "address": "Valley 345" }
newvalues = { "$set": { "address": "Canyon 123" } } mycol.update_one(myquery, newvalues) #print "customers" after the update:
for x in mycol.find():
print(x)

更新集合中的多个文档

更新符合查询条件的所有文档,需要使用 update_many() 方法。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] myquery = { "address": { "$regex": "^S" } }
newvalues = { "$set": { "name": "Minnie" } } x = mycol.update_many(myquery, newvalues) print(x.modified_count, "documents updated.")

删除文档

删除单个文档

要删除一个文档,我们使用 delete_one() 方法。

delete_one() 方法的第一个参数是 query 对象,用于定义要删除的文档。

注释:如果查询找到了多个文档,则仅删除第一个匹配项。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] myquery = { "address": "Mountain 21" } mycol.delete_one(myquery)

删除多个文档

要删除多个文档,请使用 delete_many() 方法。

delete_many() 方法的第一个参数是一个查询对象,用于定义要删除的文档。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] myquery = { "address": {"$regex": "^S"} } x = mycol.delete_many(myquery) print(x.deleted_count, " documents deleted.")

删除集合中的所有文档

删除集合中的所有文档,请把空的查询对象传递给 delete_many() 方法

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] x = mycol.delete_many({}) print(x.deleted_count, " documents deleted.")

查找文档

查找单条文档

我们可以使用 find_one() 方法,find_one() 方法返回选择中的第一个匹配项。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] x = mycol.find_one() print(x)

查找全部

如需从 MongoDB 中的表中选取数据,我们还可以使用 find() 方法。

find() 方法返回选择中的所有匹配项。

find() 方法的第一个参数是 query 对象。在这个例子中,我们用了一个空的 query 对象,它会选取集合中的所有文档。

find() 方法的第二个参数是描述包含在结果中字段的对象。此参数是可选的,如果省略,则所有字段都将包含在结果中。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] for x in mycol.find():
print(x)

返回部分字段

使用find时,第二个参数字典中,需要返回的字段设置为1,不需要返回的字段为0。

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] for x in mycol.find({},{ "_id": 0, "name": 1, "address": 1 }):
print(x)

查找多条数据

from pymongo import MongoClient
from datetime import datetime
connect = MongoClient(host='localhost', port=27017, username="root", password="123456",)
# 获取db
test_db = connect['test']
# 获取collection
collection = test_db['students']
documents = [{"author": "Mike","text": "Another post!","tags": ["bulk", "insert"], "date": datetime(2009, 11, 12, 11, 14)},
{"author": "Eliot", "title": "MongoDB is fun", "text": "and pretty easy too!", "date": datetime(2009, 11, 10, 10, 45)}]
collection.insert_many(documents=documents) # 通过条件过滤出多条document
documents = collection.find({"author": "Mike"})

计数

如果我们只想知道有多少文档与某个查询匹配,我们可以执行count_documents()操作而不是完整查询。

我们以上一个程序为例,可以对集合中的所有文档进行计数:

collection.count_documents({})  #返回结果:2

或仅与特定查询匹配的那些文档:

collection.count_documents({"author": "Mike"})  #返回结果:1

Query查询

待续

结果排序

sort() 方法按升序或降序对结果进行排序。

sort() 方法为 "fieldname"(字段名称)提供一个参数,为 "direction"(方向)提供一个参数(升序是默认方向)

按姓名的字母顺序对结果进行排序:

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] mydoc = mycol.find().sort("name") for x in mydoc:
print(x)

那么如何做降序排序?

使用值 -1 作为第二个参数进行降序排序。

sort("name", 1) # 升序
sort("name", -1) # 降序

按名称的逆向字母顺序对结果进行排序:

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] mydoc = mycol.find().sort("name", -1) for x in mydoc:
print(x)

返回结果限制

限制 MongoDB 中的结果,我们使用 limit() 方法。

limit() 方法接受一个参数,定义的数字表示返回的文档数。

把结果限定为只返回 5 个文档:

import pymongo

connect= pymongo.MongoClient("mongodb://localhost:27017/")
test_db= connect["mydatabase"]
mycol = test_db["customers"] myresult = mycol.find().limit(5) # 打印结果:
for x in myresult:
print(x)

在多进程中使用

绝不能将MongoClient实例从父进程复制到子进程。相反,父进程和每个子进程必须创建自己的MongoClient实例。例如:

# Each process creates its own instance of MongoClient.
def func():
db = pymongo.MongoClient().mydb
# Do something with db. proc = multiprocessing.Process(target=func)
proc.start()

永远不要这样做:

client = pymongo.MongoClient()

# Each child process attempts to copy a global MongoClient
# created in the parent process. Never do this.
def func():
db = client.mydb
# Do something with db. proc = multiprocessing.Process(target=func)
proc.start()

由于fork(),线程和锁之间固有的不兼容性,从父进程复制的MongoClient实例在子进程中极有可能出现死锁 。如果有可能发生这种死锁,PyMongo将尝试发出警告。