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将尝试发出警告。