Json 파일의 데이터 가공 (JavaScript) [부제: reduce]
Mongo Shell을 통해 더미데이터 생성하기 (랜덤한 값 넣기)에서 daily 데이터를 1년치를 추출했는데 이 데이터를 바탕으로 평균치를 내서 weekly 데이터를 추출하려했다.
처음에는 단순히 forEach 함수를 활용해서 Json파일에서 depth가 깊은 값을 가져오려 했는데 데이터 양이 방대하기도 하고 depth가 깊어 복잡했기 때문에 잘 되지 않았다.
그래서 아래와 같이 reduce를 활용했다.
const res = await fetch('http://localhost:3000/data');
const json = await res.json();
const division = (arr, n) => {
const length = arr.length;
const divide = Math.floor(length / n) + (Math.floor(length % n) > 0 ? 1 : 0);
const newArray = [];
for (let i = 0; i <= divide; i++) {
newArray.push(arr.splice(0, n));
}
return newArray;
};
const dividedData = division(json, 7);
let arr = [];
let timestampArr = [];
let result;
dividedData.forEach((weeklyData) => {
if (weeklyData.length) {
result = weeklyData.reduce((a, c) => {
timestampArr.push(c.timestamp);
c.dailyEC2Stats.forEach((eachData, idx) => {
if (eachData.region in a) {
a[eachData.region] = {
countTotalEC2: a[eachData.region].countTotalEC2 + eachData.countTotalEC2,
countUnmanagedEC2: a[eachData.region].countUnmanagedEC2 + eachData.countUnmanagedEC2,
countUnallowedSpec: a[eachData.region].countUnallowedSpec + eachData.countUnallowedSpec,
};
} else { // 1️⃣
a[eachData.region] = {
countTotalEC2: eachData.countTotalEC2,
countUnmanagedEC2: eachData.countUnmanagedEC2,
countUnallowedSpec: eachData.countUnallowedSpec,
};
}
});
return a;
}, {});
arr.push(result);
}
});
const timestampDivided = division(timestampArr, 7);
const weeklyTimestampArr = [];
timestampDivided.forEach((timestamp) => {
if (timestamp[0] !== undefined) {
const obj = {
start: `${timestamp[0]}`,
end: `${timestamp[timestamp.length - 1]}`,
};
weeklyTimestampArr.push(obj);
}
});
let resultArr = [];
arr.forEach((data) => {
let dataObj = { // 2️⃣
datas: {
timestamp: {
start: '',
end: '',
},
weeklyEC2Stats: [],
},
};
const obj = Object.entries(data).map(([key, value]) => ({
region: key,
AvgOfCountTotalEC2: Math.floor(value.countTotalEC2 / 7),
AvgOfCountUnmanagedEC2: Math.floor(value.countUnmanagedEC2 / 7),
AvgOfCountUnallowedSpec: Math.floor(value.countUnallowedSpec / 7),
}));
dataObj['datas']['weeklyEC2Stats'].push(...obj);
resultArr.push(dataObj);
});
resultArr.forEach((result, idx1) => {
weeklyTimestampArr.forEach((weeklyTimestamp, idx2) => {
if (idx1 === idx2) {
result['datas']['timestamp'] = weeklyTimestamp;
}
});
});
const file = 'weekly_stats_ec2_datas_v1.json';
fs.writeFile(file, JSON.stringify(resultArr), (err) => {
if (err) {
console.error(err);
}
});
a, 즉 누산기에는 객체 형태로 리전별 daily 데이터들의 합산 값을 할당할 수 있도록 1️⃣ 과 같이 구현했다. 리턴된 a는 주간마다 (7일마다) 반복되는 값이므로 빈 배열에 넣어주었다. reduce 내에서 누산기 값은 반복적으로 변하기 때문에 평균값을 위해 나누기를 하면 값이 이상하게 나온다. 이를 방지하기 위해 따로
Object.entries()
를 활용하여 객체의 모양을 다듬어줌과 동시에 평균값을 넣어줬다.
2️⃣ gold 데이터 방식으로 mongodb에 넣기 위해 datas로 각각의 데이터를 감싸는 형태로 만든 후 해당 데이터들을 resultArr라는 배열에 push했다.
✔️ 위 코드를 통해 Json 파일을 추출하면 다음과 같이 나온다.
[
{
"datas": {
"timestamp": { "start": "1/3/2022, 12:00:00 AM", "end": "1/9/2022, 12:00:00 AM" },
"weeklyEC2Stats": [
{ "region": "ap-northeast-2", "AvgOfCountTotalEC2": 71, "AvgOfCountUnmanagedEC2": 37, "AvgOfCountUnallowedSpec": 4 },
{ "region": "us-east-1", "AvgOfCountTotalEC2": 92, "AvgOfCountUnmanagedEC2": 42, "AvgOfCountUnallowedSpec": 5 },
{ "region": "ap-northeast-3", "AvgOfCountTotalEC2": 105, "AvgOfCountUnmanagedEC2": 49, "AvgOfCountUnallowedSpec": 4 },
{ "region": "ap-northeast-1", "AvgOfCountTotalEC2": 114, "AvgOfCountUnmanagedEC2": 46, "AvgOfCountUnallowedSpec": 5 },
{ "region": "sa-east-1", "AvgOfCountTotalEC2": 113, "AvgOfCountUnmanagedEC2": 57, "AvgOfCountUnallowedSpec": 5 }
]
}
},
.
.
.
{
"datas": {
"timestamp": { "start": "12/26/2022, 12:00:00 AM", "end": "12/31/2022, 12:00:00 AM" },
"weeklyEC2Stats": [
{ "region": "ap-northeast-2", "AvgOfCountTotalEC2": 62, "AvgOfCountUnmanagedEC2": 32, "AvgOfCountUnallowedSpec": 3 },
{ "region": "us-east-1", "AvgOfCountTotalEC2": 79, "AvgOfCountUnmanagedEC2": 30, "AvgOfCountUnallowedSpec": 5 },
{ "region": "ap-northeast-3", "AvgOfCountTotalEC2": 90, "AvgOfCountUnmanagedEC2": 23, "AvgOfCountUnallowedSpec": 4 },
{ "region": "ap-northeast-1", "AvgOfCountTotalEC2": 99, "AvgOfCountUnmanagedEC2": 40, "AvgOfCountUnallowedSpec": 4 },
{ "region": "sa-east-1", "AvgOfCountTotalEC2": 99, "AvgOfCountUnmanagedEC2": 49, "AvgOfCountUnallowedSpec": 3 }
]
}
}
]