How can I replace multiple object properties inside array - node.js

I'm writing a NODE.JS code that presents the user with some data about his account inside a game.
It sends a GET request to the game API, and the API returns an array with the amount of "points" the player has with every "champion" in the game. The problem is, it doesn't return the "champion" names, only their IDs:
[
{
championId: 19,
championLevel: 7,
championPoints: 116531,
},
{
championId: 24,
championLevel: 6,
championPoints: 67710,
},
{
championId: 131,
championLevel: 6,
championPoints: 67233,
}
]
I have a list with all the IDs and their related champion names, as below. I want to know if there's a way to replace all the champion IDs with their according champion name, so I can print the array with the champion names instead of the IDs, to make it easier to understand the info. I only included 3 champions here to make it simpler, but the real array has 150 champions, so I need a way to "mass edit" it.
championId: 19 equals to champion name Warwick
championId: 24 equals to champion name Jax
championId: 131 equals to champion name Diana
What i would like to print is something like:
[
{
championName: Warwick,
championLevel: 7,
championPoints: 116531,
},
{
championName: Jax,
championLevel: 6,
championPoints: 67710,
},
{
championName: Diana,
championLevel: 6,
championPoints: 67233,
}
]

The two useful array functions are map and find; map to transform the scores array, and find to do the important part of the transformation, which is looking up the name in the names array....
let scores = [{
championId: 19,
championLevel: 7,
championPoints: 116531,
},
{
championId: 24,
championLevel: 6,
championPoints: 67710,
},
{
championId: 131,
championLevel: 6,
championPoints: 67233,
}
];
let names = [{
championId: 19,
name: 'Warwick'
},
{
championId: 24,
name: 'Jax'
},
{
championId: 131,
name: 'Diana'
}
];
let scoresWithNames = scores.map(s => {
// find the matching championId in the names array
let name = names.find(n => n.championId === s.championId).name;
return { ...s, name };
});
console.log(scoresWithNames);

What you want to use is Array.prototype.map MDN. It transforms all the elements of an array using a callback function and returns the transformed array:
const champions = [
{
championId: 19,
championLevel: 7,
championPoints: 116531,
},
{
championId: 24,
championLevel: 6,
championPoints: 67710,
},
{
championId: 131,
championLevel: 6,
championPoints: 67233,
}
];
function getName(championId) {
// your logic to get the name of the champion
}
const newChampions = champions.map((c) => ({
championName: getName(c.championId),
championLevel: c.championLevel,
championPoints: c.championPoints
}));

Related

Sequelize.select returns wrong dates

I am attempting to create a web (react/sequelize) front end to an existing database.
When I perform a select from the database the returns results in sequelize have the date as off by 1 (-1).
Here is the SQL and code used to get the data:
let sql1 = 'SELECT count(RECEIVED_DATE) as CallCount, CAST(RECEIVED_DATE AS DATE) as CallDate FROM TowCalls WHERE OFFICE_ID = ? AND (RECEIVED_DATE BETWEEN dateadd(day,?, GETDATE()) AND GETDATE()) group by CAST(RECEIVED_DATE AS DATE) ORDER BY CAST(RECEIVED_DATE AS DATE)';
models.sequelize.query(sql1, { replacements: [id, -7], type: models.sequelize.QueryTypes.SELECT })
.then(function(summary) {
When I output summary to the console I get:
[
{ CallCount: 22, CallDate: '2020-12-16' },
{ CallCount: 36, CallDate: '2020-12-17' },
{ CallCount: 20, CallDate: '2020-12-18' },
{ CallCount: 12, CallDate: '2020-12-19' },
{ CallCount: 28, CallDate: '2020-12-20' },
{ CallCount: 13, CallDate: '2020-12-21' },
{ CallCount: 1, CallDate: '2020-12-22' }
]
When I use the same query in SQL Server itself I get the same counts, but all the dates are +1.
Although I never specifically set it, I believe the dates are in SQL in EST timezone.
All the users of the database are in the same timezone so I never had to worry about tracking any changes.

How do I query a set of objects with an array of values in mongoose?

I have a schema like this
const rankSchema = new Schema(
{
rank: { type: Object, default: {} },
lastUpdated: { type: Date, default: Date.now() },
},
{ minimize: false }
);
And my database has an object 'rank' with many other objects inside of it like this.
rank: {
Person1: { Stat1: 2, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 4 },
Person2: { Stat1: 4, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 2 },
Person3: { Stat1: 1, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 1 },
Person4: { Stat1: 2, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 3 }
}
Now I have an array of strings that contains a few of these people
['Person1', 'Person2']
I want to be able to find all the person objects in that array and return their stats.
So essentially the final output after using the array of strings would be
Person1: { Stat1: 2, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 4 },
Person2: { Stat1: 4, Stat2: 0, Stat3: 0, Stat4: 2, Stat5: 2 }
I tried using $in and various different queries but nothing seems to work and I am stumped.
Thanks
You could use a combination of $objectToArray and $arrayToObject to filter your object by dynamic field names but if your parameters are known when you're building your query then it's easier to use regular .find() and apply projection:
db.collection.find({},{ "rank.Person1": 1, "rank.Person2": 1})
let input = ['Person1', 'Person2'];
let entries = input.map(p => ([`rank.${p}`, 1]))
let projection = Object.fromEntries(entries);
console.log(projection);
Mongo Playground

Why Express api return two objects with same data?

I'm creating an API with Express and SQL Server as DB. I've created a post method and it works fine, but i'm having problems with the get method, 'cause it's returning two objects with the same data. This is my code:
const express = require('express');
const bodyParser = require('body-parser');
const sql = require('mssql');
const app = express();
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
const dbConfig = {
user: "theUser",
password: "thePass",
server: "theServer",
database: "theDB"
}
const executeQuery = function (res, query) {
sql.connect(dbConfig, function (err) {
if (err) {
console.log(err);
res.send(err);
}
else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, result) {
if (err) {
console.log(err);
res.send(err);
}
else {
res.send(result);
sql.close();
}
});
}
});
}
//Get All
app.get("/api/HolidayBaseApi", function (req, res) {
var query = "SELECT * FROM [HolidaysBase]";
executeQuery(res, query);
//executeQuery(res, query);
});
app.post("/api/HolidayBaseApi", function (req, res) {
var query = "INSERT INTO [HolidaysBase] (EmployeeNumber, PeriodBegin, PeriodEnd, WorkedYears, DaysPerYear, TakenDays, RemainingDays) VALUES ('"+req.body.EmployeeNumber+"','"+req.body.PeriodBegin+"','"+req.body.PeriodEnd+"','"+req.body.WorkedYears+"','"+req.body.DaysPerYear+"','"+req.body.TakenDays+"','"+req.body.RemainingDays+"')";
executeQuery(res, query);
});
const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
console.log("App now running on port", PORT);
});
I'm testing on postman and i have the next return:
{
"recordsets": [
[
{
"Id": 1,
"EmployeeNumber": 4,
"PeriodBegin": "2018-04-01T00:00:00.000Z",
"PeriodEnd": "2019-03-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 10,
"RemainingDays": 8
},
{
"Id": 2,
"EmployeeNumber": 5,
"PeriodBegin": "2018-08-02T00:00:00.000Z",
"PeriodEnd": "2018-07-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 9,
"RemainingDays": 9
},
{
"Id": 5,
"EmployeeNumber": 9,
"PeriodBegin": "2018-10-15T00:00:00.000Z",
"PeriodEnd": "2019-10-15T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 0,
"RemainingDays": 18
}
]
],
"recordset": [
{
"Id": 1,
"EmployeeNumber": 4,
"PeriodBegin": "2018-04-01T00:00:00.000Z",
"PeriodEnd": "2019-03-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 10,
"RemainingDays": 8
},
{
"Id": 2,
"EmployeeNumber": 5,
"PeriodBegin": "2018-08-02T00:00:00.000Z",
"PeriodEnd": "2018-07-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 9,
"RemainingDays": 9
},
{
"Id": 5,
"EmployeeNumber": 9,
"PeriodBegin": "2018-10-15T00:00:00.000Z",
"PeriodEnd": "2019-10-15T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 0,
"RemainingDays": 18
}
],
"output": {},
"rowsAffected": [
3
]
}
As you can see, it's returning two times the same object. Someone knows why it's returning two recordset and how can i fix it? I've been searching since yesterday, but there's no info of this behavior.
I'm using Express.js, Node and SQL Server.
I've found the solution by myself. On my executeQuery just need to get inside of the recordsets in the result:
const executeQuery = function (res, query) {
sql.connect(dbConfig, function (err) {
if (err) {
console.log(err);
res.send(err);
}
else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, result) {
if (err) {
console.log(err);
res.send(err);
}
else {
res.send(result.recordsets);
sql.close();
}
});
}
});
}
Doing this, i have kinda object inside of an object as a response:
[
[
{
"Id": 1,
"EmployeeNumber": 4,
"PeriodBegin": "2018-04-01T00:00:00.000Z",
"PeriodEnd": "2019-03-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 10,
"RemainingDays": 8
},
{
"Id": 2,
"EmployeeNumber": 5,
"PeriodBegin": "2018-08-02T00:00:00.000Z",
"PeriodEnd": "2018-07-31T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 9,
"RemainingDays": 9
},
{
"Id": 5,
"EmployeeNumber": 9,
"PeriodBegin": "2018-10-15T00:00:00.000Z",
"PeriodEnd": "2019-10-15T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 0,
"RemainingDays": 18
},
{
"Id": 6,
"EmployeeNumber": 37,
"PeriodBegin": "2018-07-27T00:00:00.000Z",
"PeriodEnd": "2019-07-27T00:00:00.000Z",
"WorkedYears": 4,
"DaysPerYear": 16,
"TakenDays": 3,
"RemainingDays": 13
},
{
"Id": 7,
"EmployeeNumber": 77,
"PeriodBegin": "2018-01-30T00:00:00.000Z",
"PeriodEnd": "2019-01-30T00:00:00.000Z",
"WorkedYears": 6,
"DaysPerYear": 18,
"TakenDays": 18,
"RemainingDays": 0
}
]
]
So, the final solution is get inside of the object and bring the first index on the request.object:
request.query(query, function (err, result) {
if (err) {
console.log(err);
res.send(err);
}
else {
res.send(result.recordsets[0]);
sql.close();
}
});

insert array using insert many function of mongoose

This is my Schema,
var trainListSchema = new mongoose.Schema({
trainNo: Number,
trainName:String,
fromStation : String,
toStation: String,
runningDays: [{type:Number}],
trainType: String,
createdTime: {type:Date , default:Date.now}})
and this is the function used to insert multiple documents.
createTrainList: function(data) {
trainList.insertMany(data, function(err, post) {
if (err) return next(err);
console.log(post);
});
}
Now as you can se runningDays is an array. While using the above method to insert data. runningDays gets inserted as 0 elements while rest of the field gets inserted successfully.
How should I go about inserting array within array using mongoose.
Help will be appreciated.
Here is the sample JSON.
[
{
"trainNo": "10104",
"trainName": "MANDOVI EXPRESS",
"fromStation": "MAO",
"toStation": "CSTM",
"days": [
0,
1,
2,
3,
4,
5,
6
],
"trainType": "MAIL EXP"
},
{
"trainNo": "10111",
"trainName": "KONKAN KANYA EX",
"fromStation": "CSTM",
"toStation": "MAO",
"days": [
0,
1,
2,
3,
4,
5,
6
],
"trainType": "MAIL EXP"
}]

MongoDB MapReduce weird bug

I'm trying this simple MapReduce operation:
function map() {
var gameDay = Math.floor((this.matchCreation - 1427846400000) / 86400000) + 1; // day of april 2015 when the game was played
this.teams.forEach (function (team){
**team.bans.forEach(function (ban){** // says bans is undefined
var value ={
banned : 1,
firstBanned: ( ((ban.pickTurn == 1) || (ban.pickTurn == 2))? 1 : 0 )
}
emit({championId: ban.championId,
day: Number(gameDay)}, value);
emit({championId: ban.championId,
day: "all"}, value);
});
});
}
function reduce(key, values) {
var a = values[0];
for(var i = 1 ; i<values.length ; i++){
var b = values[i]; // will merge 'b' into 'a'
a.banned += (b.banned? b.banned : 0);
a.firstBanned += (b.firstBanned? b.firstBanned : 0);
for (var attrname in b){
if(attrname != "banned" && attrname != "firstBanned")
a[attrname] = b[attrname];
}
}
return a;
}
matchesCollection.mapReduce(map, reduce, {
out: { reduce: "mapReduceResults" }
}, function (err, data){
if(err)
return callback (err);
callback (null, "OK");
});
It used to work before, but just when I tried to deploy the app after testing for a while, it seems to fail in this line: team.bans.forEach(function (ban){, says team.bans is undefined, although every one of the documents has a "teams" array and a "bans" array inside of each object in it, I even double checked it by querying the database and there is no document in which those fields dont exist.
So weird. The reduce function is a bit more complex but it seems to work alright, yet the map one (unlike Reduce, its supposed to be called just once per original document, right?) throws this unexplainable error. Could anyone give me some insight?
Sample input:
{
"_id": {
"$oid": "5531a63f2a3f135c11ed14a8"
},
"matchId": 1778704162,
"region": "NA",
"platformId": "NA1",
"matchMode": "CLASSIC",
"matchType": "MATCHED_GAME",
"matchCreation": 1427864425511,
"matchDuration": 1431,
"queueType": "URF_5x5",
"mapId": 11,
"season": "SEASON2015",
"matchVersion": "5.6.0.194",
"participants": [
{
"teamId": 100,
"spell1Id": 12,
"spell2Id": 4,
"championId": 81,
"highestAchievedSeasonTier": "SILVER",
"timeline": [],
"masteries": [],
"stats": {
"winner": false,
"champLevel": 19,
"item0": 1037,
"item1": 3078,
"item2": 3117,
"item3": 3035,
"item4": 3072,
"item5": 1038,
"item6": 3340,
"kills": 7,
"doubleKills": 1,
"tripleKills": 0,
"quadraKills": 0,
"pentaKills": 0,
"unrealKills": 0,
"largestKillingSpree": 3,
"deaths": 15,
"assists": 9,
"totalDamageDealt": 103191,
"totalDamageDealtToChampions": 22148,
"totalDamageTaken": 32924,
"largestCriticalStrike": 669,
"totalHeal": 2263,
"minionsKilled": 97,
"neutralMinionsKilled": 1,
"neutralMinionsKilledTeamJungle": 1,
"neutralMinionsKilledEnemyJungle": 0,
"goldEarned": 13923,
"goldSpent": 13273,
"combatPlayerScore": 0,
"objectivePlayerScore": 0,
"totalPlayerScore": 0,
"totalScoreRank": 0,
"magicDamageDealtToChampions": 6082,
"physicalDamageDealtToChampions": 15803,
"trueDamageDealtToChampions": 263,
"visionWardsBoughtInGame": 0,
"sightWardsBoughtInGame": 0,
"magicDamageDealt": 45997,
"physicalDamageDealt": 56651,
"trueDamageDealt": 543,
"magicDamageTaken": 25249,
"physicalDamageTaken": 7490,
"trueDamageTaken": 184,
"firstBloodKill": false,
"firstBloodAssist": false,
"firstTowerKill": false,
"firstTowerAssist": false,
"firstInhibitorKill": false,
"firstInhibitorAssist": false,
"inhibitorKills": 0,
"towerKills": 4,
"wardsPlaced": 2,
"wardsKilled": 0,
"largestMultiKill": 2,
"killingSprees": 1,
"totalUnitsHealed": 1,
"totalTimeCrowdControlDealt": 98
},
"participantId": 1,
"runes": []
},
... (9 more like that)
],
"participantIdentities": [],
"teams": [
{
"teamId": 100,
"winner": false,
"firstBlood": true,
"firstTower": false,
"firstInhibitor": true,
"firstBaron": false,
"firstDragon": true,
"towerKills": 6,
"inhibitorKills": 2,
"baronKills": 0,
"dragonKills": 3,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 120,
"pickTurn": 1
},
{
"championId": 37,
"pickTurn": 3
},
{
"championId": 13,
"pickTurn": 5
}
]
},
{
"teamId": 200,
"winner": true,
"firstBlood": false,
"firstTower": true,
"firstInhibitor": false,
"firstBaron": false,
"firstDragon": false,
"towerKills": 11,
"inhibitorKills": 4,
"baronKills": 0,
"dragonKills": 0,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 28,
"pickTurn": 2
},
{
"championId": 38,
"pickTurn": 4
},
{
"championId": 63,
"pickTurn": 6
}
]
}
]
}
Expected output:
{
_id: { championId: Number, day: Number }
value: { banned: Number, firstBanned: Number }
}
After that, its supposed to merge with the results of a previous MapReduce operation, copying all the fields of documents with the same key (in the reduce function), but thats irrelevant now since the error happens before...

Resources