如何在Mongo和Mongo聚合的文档中找到匹配?
问题描述:
我有以下的蒙戈JSON结构收藏 -如何在Mongo和Mongo聚合的文档中找到匹配?
{
"students":[
{
"name":"ABC",
"fee":1233
},
{
"name":"PQR",
"fee":345
}
],
"studentDept":[
{
"name":"ABC",
"dept":"A"
},
{
"name":"XYZ",
"dept":"X"
}
]
},
{
"students":[
{
"name":"XYZ",
"fee":133
},
{
"name":"LMN",
"fee":56
}
],
"studentDept":[
{
"name":"XYZ",
"dept":"X"
},
{
"name":"LMN",
"dept":"Y"
},
{
"name":"ABC",
"dept":"P"
}
]
}
现在我想要计算如下输出。 如果students.name = studentDept.name 所以我的结果应该是如下
{
"name":"ABC",
"fee":1233,
"dept":"A",
},
{
"name":"XYZ",
"fee":133,
"dept":"X"
}
{
"name":"LMN",
"fee":56,
"dept":"Y"
}
我需要使用蒙戈聚集或者是有可能得到上面给出的输出,而无需使用聚合???
答
你真的在这里问的是如何让MongoDB返回一些与你存储它的形式完全不同的东西。标准查询操作确实允许使用“限制”形式的"projection",但即使在该链接中共享的页面上的标题暗示,这实际上只是关于根据文档中的内容“限制”在结果中显示的字段已经。
因此,任何形式的“变更”都需要某种形式的聚合,聚合和mapReduce操作都允许将文档结果“重新塑形”为与输入不同的形式。也许人们对聚合框架尤其缺乏的主要是关于“聚合”的全部,实际上“重塑”概念是其实现的核心。
所以为了得到结果,你怎么想,你可以采取这样的做法,应该在大多数情况下是合适的:
db.collection.aggregate([
{ "$unwind": "$students" },
{ "$unwind": "$studentDept" },
{ "$group": {
"_id": "$students.name",
"tfee": { "$first": "$students.fee" },
"tdept": {
"$min": {
"$cond": [
{ "$eq": [
"$students.name",
"$studentDept.name"
]},
"$studentDept.dept",
false
]
}
}
}},
{ "$match": { "tdept": { "$ne": false } } },
{ "$sort": { "_id": 1 } },
{ "$project": {
"_id": 0,
"name": "$_id",
"fee": "$tfee",
"dept": "$tdept"
}}
])
或者交替只是“过滤掉”的情况下,这两个“名称“字段不匹配,然后就项目与你想要的字段的内容,如果穿越文档之间的内容是不是对你很重要:
db.collection.aggregate([
{ "$unwind": "$students" },
{ "$unwind": "$studentDept" },
{ "$project": {
"_id": 0,
"name": "$students.name",
"fee": "$students.fee",
"dept": "$studentDept.dept",
"same": { "$eq": [ "$students.name", "$studentDept.name" ] }
}},
{ "$match": { "same": true } },
{ "$project": {
"name": 1,
"fee": 1,
"dept": 1
}}
])
从MongoDB的2.6及以上的,你甚至可以做同样的事情”内联“到两个数组之间的文档。你仍然想虽然重塑你的最终输出数组的内容,但可以做的快一点:
db.collection.aggregate([
// Compares entries in each array within the document
{ "$project": {
"students": {
"$map": {
"input": "$students",
"as": "stu",
"in": {
"$setDifference": [
{ "$map": {
"input": "$studentDept",
"as": "dept",
"in": {
"$cond": [
{ "$eq": [ "$$stu.name", "$$dept.name" ] },
{
"name": "$$stu.name",
"fee": "$$stu.fee",
"dept": "$$dept.dept"
},
false
]
}
}},
[false]
]
}
}
}
}},
// Students is now an array of arrays. So unwind it twice
{ "$unwind": "$students" },
{ "$unwind": "$students" },
// Rename the fields and exclude
{ "$project": {
"_id": 0,
"name": "$students.name",
"fee": "$students.fee",
"dept": "$students.dept"
}},
])
那么,你想基本上是“改变”输出的结构,那么你需要使用的一个聚合工具来做。即使你没有真正聚合任何东西,你也可以。