目录
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':'.*公司.*'} }