2014-10-30 174 views
0

我有以下的蒙戈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" 
} 

我需要使用蒙戈聚集或者是有可能得到上面给出的输出,而无需使用聚合???

回答

0

你真的在这里问的是如何让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" 
    }}, 
]) 

那么,你想基本上是“改变”输出的结构,那么你需要使用的一个聚合工具来做。即使你没有真正聚合任何东西,你也可以。