目錄
1、Mongodb安裝
- 安裝MongoDB並啓動了服務,安裝MongoDB(windows)教程;
- pip install pymongo:安裝好Python的pymongo庫;
2、Mongodb使用文檔
3、Python_pymongo操作
(1)連接mongodb
- 創建MongoDB連接對象client
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
- 指定數據庫,調用client的屬性school,即可返回school數據庫:
db = client["school"]
- 指定集合,每個數據庫又包含許多集合(它們類似於關係型數據庫中的表),如集合students,如下命令便申明瞭Collection對象:
collection = db["students"]
- 連接數據庫總的實現
import pymongo
def connect_mongodb(config, db_name, table_name, remote_db=False):
"""
連接mongodb數據庫
:param config: host,port,username,password等配置的字典
:param db_name: 數據庫名稱
:param table_name: 表名
:param remote_db: False連接本地數據庫,True連接的是遠程數據庫
:return:
"""
client = pymongo.MongoClient(host=config['host'], port=config['port'])
db = client[db_name]
if remote_db:
db.authenticate(db['username'], db['password'])
return db[table_name]
local_config = {
"host": "localhost",
"port": 27017,
}
table = connect_mongodb(local_config, "School", "students")
(2)插入數據
- insert_one()插入單條數據(字典類型),
- insert_many()插入多條數據(字典的列表)
- 在MongoDB中每條數據其實都有一個_id屬性來唯一標識,如果沒有顯示指明該屬性,MongoDB會自動產生一個ObjectId類型的_id屬性
record1 = {'name': 'ShirMay1', 'age': 24, 'gender': 'felmale'}
record2 = {'name': 'Long', 'age': 26, 'gender': 'male'}
insert_result = table.insert_one(record1) #insert_one()插入單條數據
table.insert_many([record1, record2]) #insert_many()插入多條數據
print(insert_result)
print(insert_result.inserted_id)
# 運行結果:
# <pymongo.results.InsertOneResult object at 0x0000000002860508>
# 5c9b36b5fe0bea232819c8e7
(3)查詢數據
- find_one()查詢單條數據(返回字典類型)
- find()查詢多條數據(返回生成器對象,迭代輸出爲字典類型)
- 操作符合官方文檔
比較符號表:
符號 | 含義 | 示例 |
---|---|---|
$lt | 小於 | {‘age’:{’$lt’:20}} |
$gt | 大於 | {‘age’:{’$gt’:20}} |
$lte | 小於等於 | {‘age’:{’$lte’:20}} |
$gte | 小於等於 | {‘age’:{’$gte’:20}} |
$ne | 不等於 | {‘age’:{’$ne’:20}} |
$in | 在範圍內 | {‘age’:{’$in’:[20,23]}} |
$nin | 不再範圍內 | {‘age’:{’$nin’:[20,23]}} |
功能符號表:
符號 | 含義 | 示例 | 示例含義 |
---|---|---|---|
$regex | 匹配正則表達式 | {‘name’:{’$regex’:’^M.*’}} | name以M開頭 |
$exists | 屬性是否存在 | {‘name’:{’$exists’:True}} | name屬性存在 |
$type | 類型判斷 | {‘age’:{’$type’:‘int’}} | age的類型爲int |
$mod | 數字模操作 | {‘age’:{’$mod’[5,0]} | 年齡模5餘0 |
$text | 文本查詢 | {‘search’:‘Mike’} | text類型的屬性中包含Mike字符串 |
$where | 高級條件查詢 | {‘$where’:‘obj.fans_count==obj.follows_count’} | 自身粉絲數等於關注數 |
from bson.objectid import ObjectId
# find_one()方法查詢name爲ShirMay1的數據
query_result = table.find_one({'name': 'ShirMay1'})
# 返回字典類型
print(query_result, type(query_result))
# find_one()方法根據ObjectId來查詢
query_result_id = table.find_one({'_id': ObjectId('5e88484902bf934ff513ef37')})
# find()方法查詢年齡大於20的數據
query_ages20 = table.find({'age': {'$gt': 10}})
print(query_ages20)
for result in query_ages20:
print(result, type(result))
(4)查詢總量
- count_documents()方法查詢記錄數,傳入字典類型
# 查詢總數
count = table.count_documents({})
print(count)
# 查詢指定條件的數量
count1 = table.count_documents({'age': 24})
print(count1)
(5)排序
- sort()方法排序,pymongo.ASCENDING升序(先大寫字母后小寫字母排序),pymongo.DESCENDING降序;
sort_result = table.find().sort('name', pymongo.ASCENDING)
print([result['name'] for result in sort_result])
# 運行結果如下
# ['Hardon', 'Jordan', 'Kevin', 'Mike', 'ShirMay1']
(6)更新
- update_one()方法,指定更新的條件和更新後的數據即可
- 如:更新name爲Kevin的數據的年齡:首先指定查詢條件,然後將數據查詢出來,修改年齡後調用update_one()方法將原條件和修改後的數據傳入;
- 然後調用matched_count,modified_count屬性,可以獲得匹配的數據條數和影響的數據條數
condition = {'name': 'Kevin'}
# update_one()更新name爲Kevin的數據的年齡
student = table.find_one(condition)
student['age'] = 24
result = table.update_one(condition, {'$set': student})
print(result) # <pymongo.results.UpdateResult object at 0x0000000002A70B08>
print(result.matched_count, result.modified_count) # 1 1
# update_one()更新年齡大於20的年齡加1
condition = {'age': {'$gt': 20}}
result = table.update_one(condition, {'$inc': {'age': 1}})
print(result) # <pymongo.results.UpdateResult object at 0x0000000002A707C8>
print(result.matched_count, result.modified_count) # 1 1
- update_many()方法,指定更新的條件和更新後的數據即可
# update_many()更新年齡大於20的年齡加1
condition = {'age': {'$gt': 20}}
result = table.update_many(condition, {'$inc': {'age': 1}})
print(result) # <pymongo.results.UpdateResult object at 0x00000000029230C8>
print(result.matched_count, result.modified_count) # 3 3
(7)偏移
- 調用skip()方法,比如偏移2,就忽略前兩個元素,得到第三個及以後的元素;另外limit()方法可以指定取幾個結果
# 偏移
skip_result = table.find().sort('name', pymongo.ASCENDING).skip(2)
print([result['name'] for result in skip_result]) # ['Kevin', 'Mike', 'ShirMay1']
# 偏移取1個結果
skip_result1 = table.find().sort('name', pymongo.ASCENDING).skip(2).limit(1)
print([result['name'] for result in skip_result1]) # ['Kevin']
(8)刪除
- delete_one()刪除第一條符合條件的數據
- delete_many()刪除所有符合條件的數據
# 刪除
result = table.delete_one({'name': 'Kevin'})
print(result) # <pymongo.results.DeleteResult object at 0x0000000002A774C8>
print(result.deleted_count)
result = table.delete_many({'age': {'$lt': 25}}) # 1
print(result.deleted_count) # 3
(9)其他操作方法
- find_one_and_delete()、find_one_and_replace()、find_one_and_update()
4、實例函數
(1)連接本地數據庫或者遠程數據庫
import pymongo
def connect_mongodb(config, db_name, table_name, remote_db=False):
"""
連接mongodb數據庫
:param config: host,port,username,password等配置的字典
:param db_name: 數據庫名稱
:param table_name: 表名
:param remote_db: False連接本地數據庫,True連接的是遠程數據庫
:return:
"""
client = pymongo.MongoClient(host=config['host'], port=config['port'])
db = client[db_name]
if remote_db:
db.authenticate(db['username'], db['password'])
return db[table_name]
local_config = {
"host": "localhost",
"port": 27017,
}
table = connect_mongodb(local_config, "School", "students")
(2)更新數據數據,有則更新,無則插入
import copy
import datetime
def update_db_record(collection, db_query, record):
"""
更新數據數據,有則更新,無則插入
:param collection: 表名
:param db_query: 字典,查詢鍵,db_query = {"md5key": '1cffe16313113026764d99c582'}
:param record: 插入的數據
:return:
如果update的更新參數upsert:true,不存在會插入一條新的記錄。
$setOnInsert操作符會將指定的值賦值給指定的字段,
如果存在那麼$setOnInsert操作符不做任何處理
https://blog.csdn.net/yaomingyang/article/details/78791453
"""
def build_db_record(record):
set_data = copy.deepcopy(record)
set_data["last_updated_time"] = datetime.datetime.utcnow()
# 世界時間,比本地時間少8個小時
set_on_insert = {"created_time": datetime.datetime.utcnow()}
db_record = {"$set": set_data, "$setOnInsert": set_on_insert}
return db_record
new_record = build_db_record(record)
collection.update_one(db_query, new_record, True)
(3)修改字段鍵名
def rename_db_key(collection, before_name, after_name):
"""
修改mongodb的鍵名
:param collection: 表名
:param before_name: 修改前的鍵名, 如:"company"
:param after_name: 修改後的鍵名, 如:"company_name"
:return:
"""
collection.update_many({}, {'$rename': {before_name: after_name}})
(4)輸出mongo的數據
def mongodb_out_record(collection):
"""
mongodb的數據存儲到redis裏面
:param collection: mongodb的表
:return: 數據生成器
"""
cursor = collection.find(no_cursor_timeout=True, batch_size=5)
for record in cursor:
yield record
(5)查詢數據庫記錄總數
# 查詢數據庫記錄總數
def query_db_records(collection):
count = collection.count_documents({})
print('數據庫記錄數:', count)
return count
(6)查詢數據庫去重後的總數
def query_db_records_after_repeat(collection, record_key):
"""
查詢數據庫去重後的總數
:param collection: 表名
:param record_key: 字符串,鍵名
:return:
"""
lis = []
cursor = collection.find(no_cursor_timeout=True, batch_size=5)
for record in cursor:
lis.append(record[record_key])
print('數據庫去重後總數:', len(set(lis)))
return len(set(lis))
(7)刪除數據庫重複的數據
def delete_db_records_repeated(collection, record_key):
"""
刪除重複數據
:param collection: 表名
:param record_key: 字符串,鍵名
:return:
"""
# record_key = 'md5key'
lis, delete_count = [], 0
cursor = collection.find(no_cursor_timeout=True, batch_size=5)
for record in cursor:
if record[record_key] in lis:
result = collection.delete_one({record_key: record[record_key]})
print('刪除數', result.deleted_count)
delete_count += 1
lis.append(record[record_key])
print(f'數據庫已刪除總數:{delete_count}; 數據庫去重後總數: {len(set(lis))}')
(8)刪除數據庫指定的數據
# 刪除數據庫匹配的數據,並不是刪除重複數據
def delete_db_records_matching(collection, record_key, record_value_list):
"""
刪除數據庫匹配的數據,並不是刪除重複數據
:param collection: 表名
:param record_key: 字符串,鍵名 :'md5key'
:param record_value_list: 鍵名對應的value值列表:
['876f68ed4e3e5a2ad839f00b23a98', '3e4be58223c400cc3ae89ff13452']
:return:
"""
result = collection.delete_many({record_key: {'$in': record_value_list}})
print('數據庫已刪除總數:{}'.format(result.deleted_count))
5、mongodb其他操作
(1)設置用戶名和密碼
- 終端輸入
mongo
db.system.users.find( ) 查看有多少用戶
db.system.users.remove({user:"test"}) 刪除用戶
use admin
db.createUser( { user: "admin", pwd: "123", roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )
db.auth("admin","123")
(2)查詢數據長度大於的數據
{name:{$exists:true},$where:"(this.name.length > 3)"}
(3)查詢某一時間範圍數據
{"last_updated_time" : { "$gte" : ISODate("2019-08-12T00:00:00Z"),"$lt" : ISODate("2019-08-30T00:00:00Z")}}
(4)正則匹配查詢包含某字符
{'developer': {'$regex':'.*公司.*'} }