在 go mongodb 中的 From Table 上匹配阶段
Posted
技术标签:
【中文标题】在 go mongodb 中的 From Table 上匹配阶段【英文标题】:Match Stage on From Table in go mongodb 【发布时间】:2020-11-30 18:50:34 【问题描述】:我的 mongodb 集合
employee
_id:ObjectId(),
"emp_name":"qwert",
"emp_id":111,
"emp_dept":"XYZ"
"qualification":"PHD"
_id:ObjectId(),
"emp_name":"asdfg",
"emp_id":121,
"emp_dept":"XYZ"
"qualification":"MBA"
department
_id:ObjectId(),
"dept_id":11,
"dept_name":"XYZ",
"description":"decs",
我的 Go 代码是
type Employee struct
EmployeeName string `json:"emp_name" bson:"emp_name"`
EmployeeID int `json:"emp_id" bson:"emp_id"`
EmployeeDept string `json:"emp_dept" bson:"emp_dept"`
EmpQualification string `json:"qualification" bson:"quaification"`
EmpDepartment Department `json:"department" bson:"department"`
type Department struct
DepartmentID int `json:"dept_id" bson:"dept_id"`
DepartmentName string `json:"dept_name" bson:"dept_name"`
Description string `json:"description" bson:"description"`
EmployeeList []Employee `json:"employee_list" bson:"employee_list"`
collection := session.DB("db").C("department")
pipeline := collection.Pipe([]bson.M
"$lookup": bson.M
"from": "employee",
"localField": "dept_name",
"foreignField": "emp_dept",
"as": "employee_list",
,
"$match": bson.M
"qualification": "PHD",
,
)
err = pipeline.All(&departmentEmployees)
显示空结果
我想从我的部门集合中获取所有部门,每个部门都有“PHD”资格的员工列表。我已将我的集合和结构上传为示例。如何在查找表中使用匹配字段。
我想得到类似的输出
dept_id:11,
dept_name:'XYZ'
description:'desc'
employee_list:[
emp_name:"qwerty"
emp_id:111,
qualification:'PHD'
emp_name:"asdfg"
emp_id:222,
qualification:'PHD'
...
]
dept_id:12,
dept_name:'ABC'
description:'descwe'
employee_list:[
emp_name:"bjgk"
emp_id:865,
qualification:'PHD'
emp_name:"hkj"
emp_id:967,
qualification:'PHD'
...
]
对于第一所大学,让所有员工获得博士学位,然后在第二所大学等等。我很困惑我是否必须在查找中使用 group by in from collection?
【问题讨论】:
【参考方案1】:首先,您的 Employee.EmpQualification
字段标签中有错字:
EmpQualification string `json:"qualification" bson:"quaification"`
应该是:
EmpQualification string `json:"qualification" bson:"qualification"`
接下来,当您以employee_list
查找员工时,这将是结果中的一个新字段,因此qualification
将引用department
的字段,而不是员工的字段。
而且由于employee_list
是一个数组,你不能简单地匹配,你必须过滤数组,并用新的过滤数组替换employee_list
。
最后,您可能希望排除没有任何具有“博士”资格的员工的部门。
最终的聚合如下所示:
pipeline := collection.Pipe([]bson.M
"$lookup": bson.M
"from": "employee",
"localField": "dept_name",
"foreignField": "emp_dept",
"as": "employee_list",
,
"$addFields": bson.M
"employee_list": bson.M
"$filter": bson.M
"input": "$employee_list",
"as": "emp",
"cond": bson.M
"$eq": []interface"$$emp.qualification", "PHD",
,
,
,
,
,
"$match": bson.M
"employee_list": bson.M"$not": bson.M"$size": 0,
,
)
还要注意,上述聚合必须搜索所有部门及其员工。更好的方法是从员工开始,按资格筛选,然后按部门分组。
扩展第二种方法:一旦你有拥有 PHD 的员工,按emp_dept
分组并将员工聚集在employee_list
中,然后查找部门。然后你必须“构造”结果文档,即查找的部门必须是“根”加上一个额外的emplyee_list
(在$group
阶段收集)。
这就是它的样子:
pipeline := collection.Pipe([]bson.M
"$match": bson.M
"qualification": "PHD",
,
"$group": bson.M
"_id": "$emp_dept",
"employee_list": bson.M"$push": "$$ROOT",
,
"$lookup": bson.M
"from": "department",
"localField": "_id",
"foreignField": "dept_name",
"as": "department",
,
"$unwind": "$department",
"$replaceRoot": bson.M
"newRoot": bson.M
"$mergeObjects": []interface
"$department",
bson.M"employee_list": "$employee_list",
,
,
,
)
第二种方法的优点是它只处理拥有 PHD 的员工(确保有一个索引),只加载拥有此类员工的部门。
另请注意,最好将部门 ID 存储在员工中而不是部门名称中,如果您将来必须重命名部门,您只需在一个位置(在部门文件)。
【讨论】:
非常感谢它对我有用。我有一个问题,我在匹配字段中有四个参数,所以我必须确保所有的索引吗? @RajandeepKaur 您应该只为您的查询创建索引。如果您从不按字段过滤/查询,则应该没有索引。 当我发送请求时,每次我的结果都会改变。它基于我的匹配参数,但结果顺序发生了变化,例如我第一次得到 dept_id=1 结果,然后第二次得到 dept_id=2 结果,这是什么原因? @RajandeepKaur 无序/无序查询不保证任何顺序。如果您需要订单,请明确对结果进行排序。 我想使用 $skip 和 $limit。所以我必须在 $unwind 之后或 $replaceRoot 之后写它以上是关于在 go mongodb 中的 From Table 上匹配阶段的主要内容,如果未能解决你的问题,请参考以下文章
带有 mgo 的 Go (golang) 中的 MongoDB:如何更新记录、确定更新是不是成功并在单个原子操作中获取数据?
golang Go中的简单HTTP服务器使用mongoDB和通道