how to keep track of objects inserted in an array - javascript

When clicking add it should keep inserting object to the array and the order Id should be based from the current order id + 1 of the objects on the array so for example if if templatesDto is empty then every order in the object should increment starting from 0 when I click add
but for example there are existing data on the templatesDto
example
[
{
"id": 255,
"order": 0,
},
{
"id": 256,
"order": 1,
},
{
"id": 256,
"order": 2,
},
]
then if I click add the next order value of the new added object should be 3 since the last one is 2.
Any idea guys ? Thank you.
#html code
<button (click)="add()" mat-stroked-button mat-button class="btn-add-entitlement action-btn">
<mat-icon aria-label="Add" class="add-icon">add</mat-icon> Add
</button>
#ts code - to insert object to array
this.templatesDto= []
add() {
this.templatesDto.push({
id: 0,
order : 0,
})
}
#sample result if I click add and there are no data in templatesDto
[
{
"id": 0,
"order": 0,
},
{
"id": 0,
"order": 1,
},
{
"id": 0,
"order": 2,
}
....
]

Set order to call getNextOrder() with the function being:
function getNextOrder() {
if (this.templatesDto.length === 0) {
return 0
}
let maxOrder = 0
for (const template of this.templatesDto) {
if (template.order > maxOrder) {
maxOrder = template.order
}
}
return maxOrder + 1
}
This function goes through all objects in the array, gets the highest order value and then returns it incremented by 1.
This should also work, even if the objects in the array are not ordered according to the order property.

The best way to find the last number if there is one would be :
this.templatesDto.length > 0 ? this.templatesDto[this.templatesDto.length-1].order : 1
This way if there isn't an order already it will start at 1.
add() {
const orderNo = this.templatesDto.length > 0 ? this.templatesDto[this.templatesDto.length-1].order + 1 : 1 ;
this.templatesDto.push({
id: 0,
order : orderNo ,
})
}

The previous answers are all correct and will be sufficient for the current state of the Question.
I however would append the case, that the Order might be shuffled or at any point an element would be remove, would eventually cause some issues.
For the case, that an element in the middle would be deleted/removed, it might not cause any trouble, as the SQL-like auto-increment would still work.
But in the case, that the elements would be sorted or shuffled, the methods previously mentioned would fail, as the last element wouldn't be always the highest orderNum.
For the case, that at any point, the case occurs, i would like to submit a method, that takes this case in consideration.
add(){
// We collect the last Order number
const nextOrder = getLastOrderNum();
// We can safely insert the lastOrderNum with a single increment.
// If it is -1 we then insert 0 and so on.
this.templatesDto.push({
id: 0,
order : (nextOrder + 1)
})
}
getLastOrderNum() {
// We iterate through the entire Array and reduce it
// by returning the higher order.
// If the Array has 0 elements, we will return the beginning Value of -1,
// which will latter be incremented to 0.
// With this we can spare some logic to check if the result were 0 and not
// increment.
return this.templatesDto.reduce((a,b) => Math.(a, b.order), -1);
}

Related

Strange behavior in for-loop in JS/NodeJS

I'm working on a NodeJS/VueJS app and I encounter some strange behavior and I am not sure if it is something I am doing wrong or something else.
I have 2 arrays, one array of objects that contains campaigns and one array of objects that contains all promotions associated to all campaigns.
Each Campaign object contains, at this point, an empty array called promos, where I want to push all the promotions for each campaign.
for (var i = 0; i < campaigns.length; i++) {
for (var j = 0; j < campaignsPromo.length; j++) {
if (campaignsPromo.length > 0) {
if (campaigns[i].IDCampaign == campaignsPromo[j].IDCampaign) {
if ((campaignsPromo[j].associated == 1) && (campaignsPromo[j].validated == 1)) {
campaigns[i].promos.push(campaignsPromo[j]);
console.log("Validated Campaign ID " + campaigns[i].IDCampaign);
console.log("Promo ID " + campaignsPromo[j].IDPromo);
} else if ((campaignsPromo[j].associated == 1) && (campaignsPromo[j].validated == 0)) {
campaigns[i].unvalidatedPromos++;
console.log("Unvalidated Campaign ID " + campaigns[i].IDCampaign);
console.log("Promo ID " + campaignsPromo[j].IDPromo);
}
}
} else {
console.log("No promos!");
}
}
}
At first, the code seems to be doing what is supposed to do and it checks out with my test data set.
However, in the end, all campaigns end up having the same promotions.
Campaigns With No Promos: [{"IDCampaign":7,"campaignName":"dadsadafds","startDate":"2022-02-03","endDate":"2022-02-28","unvalidatedPromos":0,"promos":[]},{"IDCampaign":3,"campaignName":"Tarzan 3","startDate":"2022-02-02","endDate":"2022-02-06","unvalidatedPromos":0,"promos":[]},{"IDCampaign":1,"campaignName":"Tarzan","startDate":"2022-02-01","endDate":"2022-03-01","unvalidatedPromos":0,"promos":[]},{"IDCampaign":2,"campaignName":"Tarzan 2","startDate":"2022-02-01","endDate":"2022-02-08","unvalidatedPromos":0,"promos":[]},{"IDCampaign":4,"campaignName":"Tarzan 4","startDate":"2022-02-01","endDate":"2022-02-05","unvalidatedPromos":0,"promos":[]},{"IDCampaign":5,"campaignName":"Jabe 1","startDate":"2022-02-01","endDate":"2022-02-05","unvalidatedPromos":0,"promos":[]},{"IDCampaign":6,"campaignName":"dadsada","startDate":"2022-02-01","endDate":"2022-02-08","unvalidatedPromos":0,"promos":[]},{"IDCampaign":8,"campaignName":"Black Friday","startDate":"2022-02-01","endDate":"2022-02-28","unvalidatedPromos":0,"promos":[]}]
Validated Campaign ID 1
Promo ID 1119
Unvalidated Campaign ID 1
Promo ID 107
Campaigns With Promos: [{"IDCampaign":7,"campaignName":"dadsadafds","startDate":"2022-02-03","endDate":"2022-02-28","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":3,"campaignName":"Tarzan 3","startDate":"2022-02-02","endDate":"2022-02-06","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":1,"campaignName":"Tarzan","startDate":"2022-02-01","endDate":"2022-03-01","unvalidatedPromos":1,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":2,"campaignName":"Tarzan 2","startDate":"2022-02-01","endDate":"2022-02-08","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":4,"campaignName":"Tarzan 4","startDate":"2022-02-01","endDate":"2022-02-05","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":5,"campaignName":"Jabe 1","startDate":"2022-02-01","endDate":"2022-02-05","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":6,"campaignName":"dadsada","startDate":"2022-02-01","endDate":"2022-02-08","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]},{"IDCampaign":8,"campaignName":"Black Friday","startDate":"2022-02-01","endDate":"2022-02-28","unvalidatedPromos":0,"promos":[{"IDCampaign":1,"IDPromo":1119,"promoType":"CHRISTMASS","associated":1,"validated":1,"promoName":"Test Promo 1","beginDate":"2020-11-26","endingDate":"2020-11-29"}]}]
This is the content of campaignsPromo:
[ { IDCampaign: 1,
IDPromo: 1119,
promoType: 'CHRISTMASS',
associated: 1,
validated: 1,
promoName: 'Test Promo 1',
beginDate: '2020-11-26',
endingDate: '2020-11-29' },
{ IDCampaign: 1,
IDPromo: 107,
promoType: 'CHRISTMASS',
associated: 1,
validated: 0,
promoName: 'Test Promo 2',
beginDate: '2019-12-21',
endingDate: '2019-12-23' } ]
Any ideas? From where I'm standing, I am not doing anything wrong but it wouldn't be the first time I'm missing the obvious.
PS: Please ignore the fact my campaigns are called "Tarzan".
You didn't share the offending code, so I'll give a generic answer.
When the symptom is that a bunch of all objects seem to have a property that is the same array of items, it is likely caused by exactly that. Each object may be sharing the same array instance.
A typical mistake is something like the following:
var items = [];
var containers = [];
for (let i = 0; i < 3; ++i) {
items.push(i);
let container = {};
container.items = items;
containers.push(container);
}
console.log(containers);
Although one might expect, or even have intended to get 3 objects like this:
[
{ items: [ 0 ] },
{ items: [ 0, 1 ] },
{ items: [ 0, 1, 2 ] }
]
The items array is actually the same instance of an array. And what you actually get is more like:
[
{ items: [ 0, 1, 2 ] },
{ items: [ 0, 1, 2 ] },
{ items: [ 0, 1, 2 ] }
]
In fact, the stack snippet visualizer actually does a better job visualizing this because it outputs:
[
{
"items": [
/**id:3**/
0,
1,
2
]
},
{
"items": /**ref:3**/
},
{
"items": /**ref:3**/
}
]
In this way, it tries to inform you that it is actually the same array by giving it a ref:3 label and just marking the values of the other properties with the same ref:3 label as a comment.
Causes I see typically stem from a misunderstanding of what it means to assign an array to a property. Doing so does not create a copy of the array. Both objects refer to the same array.
This can be strange because: it can appear to be correct in a debugger by inspecting the contents of your array as your are stepping through a loop. Even if we had added log messages like console.log(items) or even console.log(container) inside the loop, we'd probably still not have enough of a clue that something went wrong because the contents of that one array instance change with each iteration of the loop and we can dump versions of it as text that appear to be correct, but then unwittingly change the contents of the array on the next iteration.
But if we log the entire containers array after the loop, you'll find that each object has the same instance of the array. Assining an array isn't bad if it's only one object that gets the array assigned to it, but if you assign the same array to properties of multiple objects, or in a loop, you may run into this problem.
One possible habit-breaker you can try is to inspect all objects in a second loop after your primary loop rather than sneaking your logging code directly into the first loop. It's less efficient, but if you're often making these kinds of mistakes, it can help you find problems and achieve correctness.
Another habit breaker is to console.log(JSON.stringify(foo)) rather than console.log(foo) because console.log in the browser actually remembers the reference of the object and shows you its current contents, rather than its contents at the time it was logged. This is different depending on the platform, where node.js will log as text instead of by reference.
Good luck and be careful!

Understanding the role of a variable accessing an array item/s using [ ]. (WatchAndCode related)

I am currently working my way through a WatchAndCode course.
We are building a reminders/todo-style JavaScript app.
I am struggling to understand how the [i] in the this.todos[i].todoText section of the code works. The code does not function properly without it, so it is needed.
Please can somebody explain its role? I understand you can target a specific item in an array using brackets, but I am still confused how i works exactly.
Any help would be so appreciated. If possible, can there be no alterations to the code. I am a beginner so I'm taking it step-by-step, I understand there are probably more efficient ways to go about writing the code.
Here is the full code below:
var todoList = {
todos: [],
displayTodos: function() {
if (this.todos.length === 0) {
console.log('Your todo list is empty!');
} else {
console.log('My todos:');
for (var i = 0; i < this.todos.length; i++) {
console.log(this.todos[i].todoText);
}
}
},
addTodo: function(todoText) {
this.todos.push({
todoText: todoText,
completed: false
});
this.displayTodos();
},
changeTodo: function(position, todoText) {
this.todos[position].todoText = todoText;
this.displayTodos();
},
deleteTodo: function(position) {
this.todos.splice(position, 1);
this.displayTodos();
},
toggleCompleted: function(position) {
var todo = this.todos[position];
todo.completed = !todo.completed;
this.displayTodos();
}
};
Thanks again
Basically the array consists of multiple objects, to access those objects you need to access their position in the array. The "i" in the for loop is just a variable that is going through numbers 0 to the length of the array. So the "i" will have the value 0 at start and todos[i] will actually access todos[0] (the first element of the array) and add the text from todoText to that element in the array, then the "i" becomes 1 because the for loop adds i++, it could have been written e.g i+2 if you need every 2nd element, etc.
Loops are used so you don't have to do that manually, it might be easier for you to understand if it was written manually at first :
this.todos[0].todoText
this.todos[1].todoText
this.todos[2].todoText
this.todos[3].todoText
this.todos[4].todoText
this.todos[5].todoText
this.todos[6].todoText
That's the code that happens in the loop basically so you don't have to write it all by yourself, accessing every object of the array and doing something with it. (in my example the array has 7 elements)
Hope this clarify's it a bit for you.
You can access a property's value via:
object.an_indentifier_that_matches_the_name
or
object["an_expression_that_evaluates_as_a_string_that_matches_the_name"]
Arrays are just a type of object where property names that are integers (like "1") are given special meaning.
You can use any expression (a string literal, a variable, a function call, etc) between the square brackets, so long as you get something which can be converted to a string at the end of it.
var foo = ["a", "b", "c"];
var i = 2;
console.log(foo[2]);
console.log(foo["2"]);
console.log(foo[4 / 2]);
console.log(foo[i]);
You have i in the loop:
for (var i = 0; i < this.todos.length; i++) {
console.log(this.todos[i].todoText);
}
So you have to know how does loops works. First, you declare a variable i at the first part of the loop: var i = 0;. Then, in the middle, you have a condition, it will be checked in every loop iteration. If it evaluates to true, current iteration will be executed (this code will be executed: console.log(this.todos[i].todoText);). And finally, after one iteration, variable i will be increased by 1 (it happens here: i++).
So i is just a counter, it starts from 0 and increasing by 1 after every iteration. And in first iteration the actual console.log in the body of loop will be console.log(this.todos[0].todoText);, in the second it will be console.log(this.todos[1].todoText);, and so on, while this condition: i < this.todos.length; evaluates to true.
When you're doing todos[0], it gets the first element from todos array.
For more info about for loops: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for
Firstly you should read up on arrays here: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Arrays
Lets assume this.todos equals this array:
[
{todoText: 'Foo', completed: false},
{todoText: 'Bar', completed: false},
]
If you view this like:
[
0: {todoText: 'Foo', completed: false},
1: {todoText: 'Bar', completed: false},
]
The number is the index for that entry in the array. Run snippet below to see output:
let todos = [
{todoText: 'Foo', completed: false},
{todoText: 'Bar', completed: false},
];
console.log('if `i` equals 0 then the output of `todos[i]` is:')
var i = 0;
console.log(todos[i]);
console.log('if you want to get the `todoText` value for this entry then the value of `todos[i].todoText` is:')
console.log(todos[i].todoText);
Let's suppose we have this array:
this.todos = [
/* Index "0" */ { todoText: 'my-text', otherProperty: 'blabla', },
/* Index "1" */ { todoText: 'another-text', otherProperty: 'blabla', },
/* Index "2" */ { todoText: 'last-text', otherProperty: 'blabla', },
];
// The line "this.todos[0].todoText" will show "my-text"
// The line "this.todos[2].todoText" will show "last-text"
In order to display the content of you todo-list, you have to pass through all of your todo elements, so you will make a loop through all of them with the for statement:
// Pass through your todo list.
// We began to the first element (with index "0"), the current step is stocked into "i" (var i = 0)
// Until we reach the last one (i < this.todos.length)
// When a step is over, we increment it of one (i++, or i += 1)
for (var i = 0 ; i < this.todos.length ; i++)
For each one, you write its content:
console.log(this.todos[i].todoText);
You precised that your first element in the index "0", so it's like you remplaced "i" by "0":
console.log(this.todos[0].todoText); // Remember, "this.todos[0].todoText" show "my-text".
And so on, until you loop through your last element:
console.log(this.todos[1].todoText); // Remember, "this.todos[1].todoText" show "another-text".
console.log(this.todos[2].todoText); // Remember, "this.todos[2].todoText" show "last-text".
Your loop is executed as long as i < this.todos.length is true. It ends after that because this.todos[3] does not exist and return false.

How can I remove data by index array which is stored in local storage?

If I console.log(localStorage.getItem("cartCache")), the result like this :
{"dataCache":[{"id":20,"quantity":1,"total":100000,"request_date":"27-08-2017 20:31:00"},{"id":53,"quantity":1,"total":200000,"request_date":"27-08-2017 20:38:00"}],"expired":"2017-08-28T03:55:21.521Z"}
I want to remove the data in the cache by index array
For example, When I remove index array = 0, the result to be like this :
{"dataCache":[{"id":53,"quantity":1,"total":200000,"request_date":"27-08-2017 20:38:00"}]}
Another example, When I remove index array = 1, the result to be like this :
{"dataCache":[{"id":20,"quantity":1,"total":100000,"request_date":"27-08-2017 20:31:00"}]}
How can I do it?
I try like this :
var deleteIndex = 1;
var retrievedObj = localStorage.getItem("cartCache")
delete retrievedObj['dataCache'][deleteIndex];
It seems that is not the right way
localStorage.getItem("cartCache") returns you two objects - dataCache and expired. If you want to remove the element n of dataCache, remove it by
localStorage.getItem("cartCache").dataCache.splice(n,1);
To fit it in your code:
var deleteIndex = 1;
var retrievedObj = localStorage.getItem("cartCache");
retrievedObj.dataCache.splice(deleteIndex,1);
Then console.log your localStorage again and you'll see the element removed.
You can use splice to remove an item from the array
// Clearing all localStorage value. No need to use below line in your code
localStorage.clear();
// to be stored object
var x = {
"dataCache": [{
"id": 20,
"quantity": 1,
"total": 100000,
"request_date": "27-08-2017 20:31:00"
}, {
"id": 53,
"quantity": 1,
"total": 200000,
"request_date": "27-08-2017 20:38:00"
}],
"expired": "2017-08-28T03:55:21.521Z"
}
// Initially storing it in local storage using JSON.stringify
localStorage.setItem('storeData', JSON.stringify(x));
// Once stored retrieving the value using JSON.parse
var getItem = JSON.parse(localStorage.getItem('storeData'));
// setting the dataCache with new array. The new array will be created as splice is used. splice is used to remove an item from array,
//0 is the index of the array, while second parameter 1 is to represent how many item to be removed starting from 0 ndex
getItem.dataCache = getItem.dataCache.splice(0, 1);
console.log(getItem); // the modified object
// after operation setting it to local storage
localStorage.setItem('storeData', JSON.stringify(getItem))
DEMO
Keyword "delete" deletes deleteIndex only in retrieveObj it doesn't update your localStorage value. In order to update localStorage use:
var deleteIndex = 1;
var retrievedObj = localStorage.getItem("cartCache")
delete retrievedObj['dataCache'][deleteIndex];
localStorage.setItem("cartCache", retrieveObj)

Mongoose pagination with first item instead of skip [duplicate]

I'm trying to calculate the skip value for a given record in a mongo db collection using the php driver. So taking a given record, find out the index of that record within the entire collection. Is this possible?
Currently I'm selecting all records and manually doing an index of on the array of results.
This is called "forward paging" which is a concept you can use to "efficiently page" through results in a "forward" direction when using "sorted" results.
JavaScript logic included (because it works in the shell), but not hard to translate.
The concept in general:
{ "_id": 1, "a": 3 },
{ "_id": 2, "a": 3 },
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
Consider those "already sorted" documents ( for convienience ) as an example of results we want to "page" by "two" items per page.
In the first instance you do something like this:
var lastVal = null,
lastSeen = [];
db.collection.find().sort({ "a": -1 }).limit(2).forEach(function(doc) {
if ( lastVal != doc.a ) {
lastSeen = [];
}
lastVal = doc.a;
lastSeen.push( doc._id );
// do something useful with each document matched
});
Now those lastVal and lastSeen are something you store in something like a "session variable" than can be accessed on the next request in terms of web applications, or otherwise something similar where not.
What they should contain though are the very last value you were sorting on and the list of "unique" _id values that were seen since that value did not change. Hence:
lastVal = 3,
lastSeen = [1,2];
The point is that when the request for the "next page" comes around then you want to use those variables for something like this:
var lastVal = 3,
lastSeen = [1,2];
db.collection.find({
"_id": { "$nin": lastSeen },
"a": { "$lte": lastVal }
}).sort({ "a": -1 }).limit(2).forEach(function(doc) {
if ( lastVal != doc.a ) {
lastSeen = [];
}
lastVal = doc.a;
lastSeen.push( doc._id );
// do something useful with each document matched
});
What that does is "exclude" all values of _id that are recorded in lastSeen from the list of results, as well as make sure that all results need to be "less than or equal to" ( descending order ) the lastVal recorded for the sort field "a".
This yields the next two results in the collection:
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
But after processing our values now look like this:
lastVal = 2,
lastSeen = [4];
So now the logic follows that you don't need to exclude the other _id values seen before since you are only really looking for values of "a" than are "less than or equal to" the lastVal and since there was only "one" _id value seen at that value then only exclude that one.
This of course yields the next page on using the same code as just above:
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
That is the most effiecient way to "forward page" through results in general and is particularly useful for efficient paging of "sorted" results.
If however you want to "jump" to page 20 or similar action at any stage then this is not for you. You are stuck with the traditional .skip() and .limit() approach to be able to do this by "page number" since there is no other rational way to "calculate" this.
So it all depends on how your application is implementing "paging" and what you can live with. The .skip() and .limit() approach suffers the performance of "skipping" and can be avoided by using the approach here.
On the other hand, if you want "jump to page" then "skipping" is your only real option unless you want to build a "cache" of results. But that's another issue entirely.

Using two "for" loops in a Mongo query - only passing first or last item

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.

Categories