I have a query that aggregates based on a collection of documents (tickets). It looks for tickets with a pre-defined DisplayLabel
and any AssignedToPerson
. It then averages the WorkingDuration
of each person's tickets and organizes them into a document of objects, with each object including the AssignedToPerson
and the average of their WorkingDuration
. It then sorts them by the newly created key called WorkingDurationAvg
.
It grabs its label
from a list of distinct DisplayLabels
from the Requests
collection.
var label = db.Requests.distinct("DisplayLabel");
var raw = db.Requests.aggregate([
{$match:{"DisplayLabel": (label[5]) }},
{
$group:
{
_id: "$AssignedToPerson",
WorkingDurationAvg : { $avg : "$WorkingDuration" }
}
},
{$project:{_id : 1, "WorkingDurationAvg": 1}},
{$sort : {"WorkingDurationAvg":1 }}
])
This gets assigned to raw
, therefore raw.result
would return something like this:
{
"0" : {
"_id" : "Bob",
"WorkingDurationAvg" : 50.0000000000000000
},
"1" : {
"_id" : "Jim",
"WorkingDurationAvg" : 75.0000000000000000
}
}
I then loop through each of the objects in raw.result
and append a score to an array object that has the matching label[5]
, into a predefined field called time
, based on their position.
var count = raw.result.length;
raw.result.forEach
(
function()
{for (var i = 0; i < 1000; i++)
db.test.update(
{ "name" : (raw.result[i]._id), "dogs.capname" : (label[5]) },
{$set: {"dogs.$.time": (count - i) / count }},
print(raw.result[i]._id)
)})
This works. The problem I'm running into, if you look at the first code snippet, is that I'm manually calling the DisplayLabel
array number (in this example, I'm calling the [5]
th element of label
). I also call this [5]
th element in the third code snippet. I want to iterate through each value of label
. Meaning the query will run using label[0]
, and then label[1]
, and then label[2]
, and so on...
Here's what I tried:
var label = db.Requests.distinct("DisplayLabel");
for (var x=0;x<100;x++){ //newly created for loop, goes up to 100
var raw = db.Requests.aggregate([
{$match:{"DisplayLabel": (label[x]) }}, //[5] is changed to [x]
{
$group:
{
_id: "$AssignedToPerson",
WorkingDurationAvg : { $avg : "$WorkingDuration" }
}
},
{$project:{_id : 1, "WorkingDurationAvg": 1}},
{$sort : {"WorkingDurationAvg":1 }}
])
// } <<-- A bracket here would return the same thing as entering "label[100]"
var count = raw.result.length;
raw.result.forEach
(
function()
{for (var i = 0; i < 1000; i++)
db.test.update(
{ "name" : (raw.result[i]._id), "dogs.capname" : (label[x]) },
{$set: {"dogs.$.time": (count - i) / count }},
)})
} // <<-- A bracket here returns the same thing as entering "label[0]"
See the notes for what the curly brackets ending the "for" loop do.
From what I can tell, the problem is JavaScript based and not Mongo based. With the curly bracket higher up, the aggregation runs 101 times, but only returns the [100]
th value into the next function. With the curly bracket at the end, the function only runs once and returns the result with the [0]
th value. So the function either runs 101 times and THEN passes that value, or it's a "one and done".
I've also tried using this answer's idea, but I can only get it to return the [100]
th value using this method.
I know that I'm able to iterate through each raw.result
because if I run this query as-is, but without everything below raw.result.forEach
, I am able to print each iteration of raw.result
. Adding the forEach
limits me to the last iteratated item.