我有一张桌子并保存如下:
{ "_id" : ObjectId("5716617f4af77ca97a9614bd"), "count" : 1, "author" : "Tony", "music" : [ { "_id" : ObjectId("571661cd4af77ca97a9614c1"), "count" : 2, "author" : "Tony" } ] }
{ "_id" : ObjectId("5716617f4af77ca97a9614be"), "count" : 2, "author" : "Joe", "music" : [ { "_id" : ObjectId("571661cd4af77ca97a9614c0"), "count" : 1, "author" : "Joe" } ] }
{ "_id" : ObjectId("5716617f4af77ca97a9614bf"), "count" : 3, "author" : "Mary", "music" : [ ] }
我希望找到“$ count”>的记录数量。 “$ music.count”。但当我做{$ unwind:“$ music”}时,我得到了以下信息:
{ "_id" : ObjectId("5716617f4af77ca97a9614bd"), "count" : 1, "author" : "Tony", "music" : { "_id" : ObjectId("571661cd4af77ca97a9614c1"), "count" : 2, "author" : "Tony" } }
{ "_id" : ObjectId("5716617f4af77ca97a9614be"), "count" : 2, "author" : "Joe", "music" : { "_id" : ObjectId("571661cd4af77ca97a9614c0"), "count" : 1, "author" : "Joe" } }
第三条记录消失了。我怎样才能得到如下结果:
{ "_id" : ObjectId("5716617f4af77ca97a9614bd"), "count" : 1, "author" : "Tony", "music" : { "_id" : ObjectId("571661cd4af77ca97a9614c1"), "count" : 2, "author" : "Tony" } }
{ "_id" : ObjectId("5716617f4af77ca97a9614be"), "count" : 2, "author" : "Joe", "music" : { "_id" : ObjectId("571661cd4af77ca97a9614c0"), "count" : 1, "author" : "Joe" } }
{ "_id" : ObjectId("5716617f4af77ca97a9614bf"), "count" : 3, "author" : "Mary", "music" : {"count": 0} }
初始记录是通过$ loopup得到的,总代码如下:
db.bookAuthors.aggregate([{
$lookup:{from:"musicAuthors", localField:"author", foreignField:"author",as:"music"}},
{$unwind:"$music"},
{$project:{_id:"$author",count:1,music:1}},
{$match:{$gt:["$count","$music.count"]}},
{$group:{_id:null,count:{$sum:1}}}
])
如何查找“$ count”>的记录数量? “$ music.count”?在这个例子中,结果应该是2.但是现在由于解开问题,我得到1.谢谢。
答案 0 :(得分:19)
在MongoDB 3.2中(如果您有preserveNullAndEmptyArrays
,则使用),$unwind
运算符具有db.bookAuthors.aggregate([
{ "$lookup":{
"from": "musicAuthors",
"localField": "author",
"foreignField": "author",
"as": "music"
}},
{ "$unwind": { "path": "$music", "preserveNullAndEmptyArrays": true },
{ "$project": {
"count": 1,
"author": 1,
"music": {
"$ifNull": [ "$music", { "$literal": { "count": 0 } }] },
}
}}
])
选项。这会将行为更改为“不”从数组实际上为“空”的结果中删除文档:
1:1
在这种情况下,$ifNull
会替换缺失值。
但实际上,由于您的关联位于db.bookAuthors.aggregate([
{ "$lookup":{
"from": "musicAuthors",
"localField": "author",
"foreignField": "author",
"as": "music"
}},
{ "$project": {
"count": 1,
"author": 1,
"music": {
"$ifNull": [
{ "$arrayElemAt": [ "$music", 0 ] },
{ "$literal": { "count": 0 } }
]
}
}}
])
,因此您可以完全放弃$unwind
,只需替换空数组:
0
如果$arrayElemAt
在db.bookAuthors.aggregate([
{ "$lookup":{
"from": "musicAuthors",
"localField": "author",
"foreignField": "author",
"as": "music"
}},
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$cond": {
"if": {
"$gt": [
"$count",
{ "$sum": {
"$map": {
"input": "$music",
"as": "el",
"in": "$$el.count"
}
}}
]
},
"then": 1,
"else": 0
}
}
}
}}
])
索引处找不到任何内容(因此为“空”),那么$ifNull
将像以前一样返回备用值。当然它确实找到了什么,然后返回该值。
但同样,您的具体问题仍有更好的解决方案,同样不需要$unwind
。因为您可以使用数组“in-line”计算“计数”条件:
$sum
这里$sum
运算符用在它的两个用例中,因为它是传统的“累加器”,并且是数组中“求和”值的新角色。 $map
运算符查看每个数组元素并将值返回0
以生成总计。 “空”数组将返回"count"
。
然后进行$cond
比较,以确定数组中返回的总数是否小于文档上的true
属性。 1
为累加器返回false
的位置,以及0
获取2
的位置。
最终结果当然是public function update(CreateJournalRequest $request, $course_id){
$input = $request->all();
foreach ($input['id'] as $i => $log_id){
$data = [
'user_id' => \Auth::user()->id,
'course_id' => $course_id,
'weeks' => $i + 1,
'work_description' => $input['work_description'][$i],
'instructor_comments' => $input['instructor_comments'][$i],
'status' => $input['status'][$i],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
Journal::where('id', $log_id)->update($data);
}
return redirect('/student/home');
}
,因为“第一”和“第三”文档实际上与累加器内的条件匹配。所以这确实是最有效的方法,即使它在这个过程中看起来有点“长篇大论”。