# 介绍mongodb auto reference # author: luw2007@gmai.com # 请在本地测试环境上使用 from pymongo import MongoClient from pymongo.son_manipulator import AutoReference, NamespaceInjector from bson import DBRef DB_NAME = 'test' PEOPLE_TABLE = 'people' MSG_TABLE = 'msg' # 没有添加自动引用的表, 方便查询原始的数据 no_reference_db = MongoClient()[DB_NAME] raw_people = no_reference_db[PEOPLE_TABLE] raw_msg = no_reference_db[MSG_TABLE] # 清空历史数据 _ = raw_people.remove() _ = raw_msg.remove() # 连接到本地的mongodb, 并打开自动引用 db = MongoClient()[DB_NAME] db.add_son_manipulator(AutoReference(db)) db.add_son_manipulator(NamespaceInjector()) people = db[PEOPLE_TABLE] msg = db[MSG_TABLE] # 新增 peter = {'name': 'peter'} john = {'name': 'john'} marry = {'name': 'marry'} huangz = {'name': 'huangz', 'friends': [peter, john, marry]} people.insert([peter, john, marry, huangz]) # 开启自动引用后, 会增加 ``{'_ns': 'people'}`` print(peter) # 对比开启自动引用前后数据差异 # 数据库中是 DBRef类型的字段, 自动引用后将"DERef" 转换成对应的真实字段 #在数据库中 raw_people.find_one({'name': 'huangz'})['friends'][0] # 自动引用后 huangz['friends'][0] # 搜索DBRef 字段 people.find_one({'friends': DBRef(PEOPLE_TABLE, peter['_id'])}, {'name': 1}) # 删除 use $pull 删除掉数组中的DBRef peter_ref = DBRef(PEOPLE_TABLE, peter['_id']) people.update({'friends': peter_ref}, {'$pull': {'friends': peter_ref}}) # 某条数据中即使有自动引用, 这条数据依然是普通的mongodb数据. 直接使用remove 就可以删除 people.remove(marry) '''由于mongodb 不提供事务, 而且目前自动引用不提供关联删除功能 所以自动引用中的对象删除了, 开启自动引用后会显示None, 因此删除时需要自行处理引用的情况.''' print('haungz 中不会自动删除 friends中的marry字段, \n由 %r 变成 %r' % ( huangz['friends'][-1], people.find_one({'_id': huangz['_id']})['friends'][-1]) ) # 手工删除掉 friends 中的 'marry', 重新保存 huangz['friends'].pop() people.save(huangz) # 此时数据中已经没有marry people.find_one({'_id': huangz['_id']})['friends'] # 跨表 msg.insert([{'from': huangz, 'to': peter, 'message': 'from hangz to peter'}, {'from': huangz, 'to': john, 'message': 'from hangz to john'}, {'from': huangz, 'to': marry, 'message': 'from hangz to marry'}]) # 自动处理引用前 '''注意from, to 字段''' raw_msg.find_one({'to': DBRef(PEOPLE_TABLE, peter['_id'])}) # 自动处理引用后 to_peter = msg.find_one({'to': DBRef(PEOPLE_TABLE, peter['_id'])}) print(to_peter) '''注意 from.friends 字段也会被自动引用''' to_peter['from']['friends']