Django直连MongoDB无模型时如何关联归一化员工任职数据
实现方法
你这种无外键的两个集合做关联嵌套,两种方案都能实现,按需选就行。
方案1:MongoDB聚合查询直接返回嵌套结果(推荐,性能更好)
直接用MongoDB原生的$lookup聚合算子做关联,一次查库就拿到最终结构,不用在Python代码里二次处理数据。
假设你已经拿到pymongo/Djongo初始化好的集合对象:employee_col是员工集合,employment_col是任职记录集合,代码如下:
def query_employees_detail(): agg_pipeline = [ { "$lookup": { "from": "employment", # 填你Mongo里实际存任职记录的集合名 "localField": "emp_id", # 员工表用于关联的字段 "foreignField": "emp_id", # 任职记录表用于匹配的字段 "as": "employment_status" # 关联后的任职记录存在这个字段下 } } # 要加筛选、排序、字段排除的话,直接往这个数组里加对应聚合阶段就行 # 比如要去掉返回结果里的Mongo默认_id字段,就加{"$project": {"_id": 0}} ] # 执行聚合,直接得到结构符合要求的结果列表 return list(employee_col.aggregate(agg_pipeline))
查出来的结果里,每个员工文档自动带employment_status字段,值是该员工对应所有任职记录的数组,没有任职记录的员工这个字段是空数组,和你要的结构完全匹配。
方案2:Python层手动组装数据
如果不想写聚合管道,或者组装过程中要加很多自定义逻辑,可以分别查两个集合的数据,在内存里做匹配,适合数据量不大的场景:
def query_employees_detail(): # 1. 查所有员工数据,可自行加筛选条件、指定返回字段 all_employees = list(employee_col.find({}, {"_id": 0})) # 2. 查所有任职记录 all_employments = list(employment_col.find({}, {"_id": 0})) # 3. 先把任职记录按emp_id分组,避免双层循环浪费性能 employment_group = {} for record in all_employments: eid = record["emp_id"] if eid not in employment_group: employment_group[eid] = [] employment_group[eid].append(record) # 4. 给每个员工挂载对应的任职记录 for emp in all_employees: emp["employment_status"] = employment_group.get(emp["emp_id"], []) return all_employees
这个方式逻辑完全可控,组装过程中你可以随便加逻辑,比如给任职记录按日期排序、过滤掉无效的记录之类的。
补充说明
注意: 单条员工详情查询的话,不管用哪种方案,都记得在查询/聚合阶段加上emp_id的过滤条件,不要全表扫描后再取单条,性能差很多。
- 数据量超过10万的场景优先选方案1,MongoDB原生聚合的关联效率远高于Python层内存组装。
内容的提问来源于stack exchange,提问作者Sherlin Susanna
相关产品推荐
相关产品推荐

