sequelize distinct ,count and grouping - javascript

I have a database of uploaded files , each file can have one of 4 stages; recieved, converting, done and failed. need to bring a count of each stage for each. The date is stored in the "ReceivedAt" column in ms.
this is my code. it works, but it takes a long time to get all the information out.
const dates = await Job.aggregate("recievedAt", "DISTINCT", { plain: false });
const dates_sorted = dates.sort((a, b) => a - b);
const rev_date = dates_sorted.reverse();
let day;
const summery_by_date = [];
try {
await Promise.all(
rev_date.map(async (date) => {
const string_d = new Date(Number(date.DISTINCT)).toDateString();
if (!(day === string_d)) {
day = string_d;
const d_num = new Date(Number(date.DISTINCT));
const date_midnight = d_num.toISOString().split("T")[0];
const beaging_date = Number(new Date(date_midnight).getTime());
const end_date = Number(beaging_date + 86400000);
const total = await Job.count({
where: {
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
});
const failed = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "failed" },
],
},
});
const converting = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "converting" },
],
},
});
const recieved = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "recieved" },
],
},
});
const done = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "done" },
],
},
});
summery_by_date.push({
date: beaging_date,
total: total,
failed: failed,
converting: converting,
recieved: recieved,
done: done,
});`
thanks in advance

Related

How to check if a value in an array is present in other object and accordingly return a new object

I have an array
const dataCheck = ["Rohit","Ravi"];
I have another array of object
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
I want to check if any value in dataCheck is present in the userData and then return a new array with the below data
const newData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit", status: "present" },
{ name: "Ravi", status: "present" },
];
I tried to do something using loops but not getting the expected results
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" }
];
let newDataValue = {};
let newData = [];
userData.forEach((user) => {
const name = user.name;
dataCheck.forEach((userName) => {
if (name === userName) {
newDataValue = {
name: name,
status: "present"
};
} else {
newDataValue = {
name: name
};
}
newData.push(newDataValue);
});
});
console.log(newData);
My trial gives me repeated results multiple results which is just duplicates
You should use map() and a Set.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const set = new Set(dataCheck);
const output = userData.map(data => set.has(data.name) ? ({...data, status: "present"}): data)
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
A Set allows for lookups in O(1) time and therefore this algorithm works in O(n) time. If you would use the array for lookups (e.g. using indcludes(), find() etc.) the runtime would be O(n²). Although this will certainly not matter at all for such small arrays, it will become more relevant the larger the array gets.
map() is used here because you want a 1:1 mapping of inputs to outputs. The only thing to determine then is, what the output should be. It is either the input, if the value is not in the Set, or it is the input extended by one property status set to "present". You can check for the presence in a Set using the has() method and can use the ternary operator ? to make the decision which case it is.
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
// map through every object and check if name property
// exists in data check with help of filter.
// if it exists the length of filter should be 1 so
// you should return { name: el.name, status: "present" } else
// return { name: el.name }
let newData = userData.map((el) => {
if (dataCheck.filter((name) => name === el.name).length > 0) {
return { name: el.name, status: "present" };
} else {
return { name: el.name };
}
});
console.log("newdata: ", newData);
A better approach would be to use map over userData array, find for matching element in dataCheck, if found return matching element + a status key or just return the found element as it is.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const getUpdatedObject = () => {
return userData.map(userData => {
const userDetail = dataCheck.find(data => userData.name === data);
if(userDetail) return {userDetail, status:"present"}
else return {...userData}
});
}
console.log(getUpdatedObject())
Working fiddle
Loop through userData, check if name is includes in dataCheck. If true add status 'present'.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
for (let user of userData) {
if(dataCheck.includes(user.name)) {
user.status = 'present'
}
}
console.log(userData)
You are seeing repeated results due to the second loop dataCheck.forEach((userName) => { as every loop of dataCheck will fire the if/else statement and add something to the final array. However many values you add to dataCheck will be however many duplicates you get.
Only need to loop through one array and check if the value is in the other array so no duplicates get added.
const dataCheck = ["Rohit", "Ravi"];
const userData = [{ name: "Sagar" }, { name: "Vishal" }, { name: "Rohit" }, { name: "Ravi" }];
let newDataValue = {};
let newData = [];
// loop thru the users
userData.forEach((user) => {
// set the user
const name = user.name;
// check if in array
if (dataCheck.indexOf(name) >= 0) {
newDataValue = {
name: name,
status: "present",
};
}
// not in array
else {
newDataValue = {
name: name,
};
}
newData.push(newDataValue);
});
console.log(newData);
So you will do like this :
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const newUserData = userData.map( user => {
dataCheck.forEach( data => {
if( data === user.name )
user.status = "present";
});
return user;
} );
console.log( newUserData );

I am creating a function that takes a filtered array and outputs a TextBlock in an adaptive card with the birthdays of users(Person and date of birth)

I am creating a function that takes a filtered array and outputs a TextBlock in an adaptive card with the birthdays of users (Person and date of birth), I wrote the code but I have an error: [onTurnError] unhandled error: Error: Payload is incorrect
this is a teamsBot file.js
if (invokeValue.action.verb === "event5") {
const res = await axios.get("https://365.sharepoint.com/sites/Manage/_api/Web/Lists(guid'')/Items", {
headers: {
'Authorization': 'Bearer token'
}
})
console.log(res);
let today = new Date();
// const tmp1 = res.data.value.filter(item => moment(item.field_4).format('MM') === moment(today).format('MM'));
// console.log(tmp1);
const tmp1 = res.data.value.map(val => {
return{
name: val.field_1,
bdate: new Date(val.field_4)
}
})
const currentMonth = (new Date()).getMonth()
const filtredEmployees = tmp1.filter(employee => {
return employee.bdate.getMonth() === currentMonth
})
console.log(filtredEmployees);
const card = cards.card1(tmp1);
await context.sendActivity({ attachments: [CardFactory.adaptiveCard(card)] });
return { statusCode: 200 };
}
and this is cards.js
const card1 = (tmp1) => {
return[
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content":{
"type": "AdaptiveCard",
"version": "1.4",
"body": [
tmp1.map(item => {
return(
{
"type": "TextBlock",
"text": item.bdate,
"wrap": true
}
)
})
],
"actions": [
{
"type": "Action.Execute",
"title": "На главную",
"verb": "hello",
"fallback": "Action.Submit"
}
]
}
}
]
}
module.exports.cards = {
card1: card1
}

How do I query the contents of my list in order?

I am trying to create DNS api. Since my records are asynchronous on node js, I cannot match record names and record values. How can I sync this build? or how can I add the record names next to the record values?
import dns from 'dns';
const rrtype="*";
const obj= ["A","MX","CNAME","NS","TXT"];
var myobj = [];
export const getAllRecords = (req,res) => {
const {domain} = req.params;
for(var i=0;i<obj.length;i++){
dns.resolve(domain, obj[i], (err, records) => myobj.push(records));
}
setTimeout(function(){
res.send(myobj);
}, 1000);
myobj = [];
}
You can use Promise.All like #Barmar suggested or if you want to do the dns lookups sequencially you can do something like this, notice the use of dns.promises.resolve which returns a promise and not a callback, and the use of async/await. I tested it as a script so i'm also putting the output of the call to getAllRecords({ params: { domain: "gmail.com" } });
import dns from "dns";
const rrtype = "*";
const obj = ["A", "MX", "CNAME", "NS", "TXT"];
export const getAllRecords = async (req, res) => {
const { domain } = req.params;
let myObj = [];
for (let i = 0; i < obj.length; i++) {
try {
const res = await dns.promises.resolve(domain, obj[i]);
myObj.push({ recordType: obj[i], recordValue: res });
} catch (err) {
console.log(err);
}
}
// Debug results
console.log(JSON.stringify(myObj, null, 4));
setTimeout(() => {
// res.send(myObj);
console.log(" === END ===");
}, 1000);
};
// Simple test
getAllRecords({ params: { domain: "gmail.com" } });
Output:
> node dnsTest.js
Error calling resolve Error: queryCname ENODATA gmail.com
at QueryReqWrap.onresolve [as oncomplete] (internal/dns/promises.js:170:17) {
errno: 'ENODATA',
code: 'ENODATA',
syscall: 'queryCname',
hostname: 'gmail.com'
}
[
{
"recordType": "A",
"recordValue": [
"142.250.184.5"
]
},
{
"recordType": "MX",
"recordValue": [
{
"exchange": "alt4.gmail-smtp-in.l.google.com",
"priority": 40
},
{
"exchange": "alt2.gmail-smtp-in.l.google.com",
"priority": 20
},
{
"exchange": "alt3.gmail-smtp-in.l.google.com",
"priority": 30
},
{
"exchange": "gmail-smtp-in.l.google.com",
"priority": 5
},
{
"exchange": "alt1.gmail-smtp-in.l.google.com",
"priority": 10
}
]
},
{
"recordType": "NS",
"recordValue": [
"ns1.google.com",
"ns3.google.com",
"ns2.google.com",
"ns4.google.com"
]
},
{
"recordType": "TXT",
"recordValue": [
[
"globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
],
[
"v=spf1 redirect=_spf.google.com"
]
]
}
]
=== END ===

How to return data from inside Promise, reduce, format?

I've been stuck on trying to make this test pass for awhile. I want it to return an array of 3 objects of mockExpectedResult
Step 1: Reduce scheduled operations array (omit items that don't have path). This should return array of strings of InventoryItemPath
Step 2: Reduce over InventoryItemPath array (freeRewardsInventory), make async call to service (getItem is a mock of this async GET request) which returns Promise.
Step 3: Reducer over freeRewardsRaw Promises, format into mockExpectedResult
Step 4: Return output (Array of mockExpectedResults)
I think my main issue is that I'm not awaiting all of these promises (missing one await maybe?)
Thanks for helping.
const mockScheduledOperation = {
Ranks: [{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
},
{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
},
{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
}
]
};
const getAllRewards = async () => {
const freeRewardsInventory = mockScheduledOperation.Ranks.reduce(
(agg, rank) => {
if (rank.FreeRewards.InventoryRewards.length > 0) {
const rewardList = rank.FreeRewards.InventoryRewards.reduce(
(agg, reward) => {
if (reward.InventoryItemPath) {
agg = reward.InventoryItemPath;
}
return agg;
},
''
);
agg.push(rewardList);
}
return agg;
},
[]
);
const getItem = async (rewardPath: string) => mockReturnedItem;
const freeRewardsRaw = freeRewardsInventory.reduce < [] > (
async (agg, rewardPath) => {
const promise = await getItem(rewardPath);
agg.push(promise);
return agg;
},
[]
);
const formattedRewards = await Promise.all(freeRewardsRaw).then(
(response) => {
response.reduce < ProgressionRewards[] > ((agg, res) => {
const formattedReward: ProgressionRewards = {
// free = unlocked, paid = locked
locked: false,
level: null,
difficulty: res.CommonData.Quality || null,
date: res.CommonData.DateReleased.ISO8601Date || null,
rewardAttachments: [{
image: res.CommonData.DisplayPath.Media.MediaUrl.Path || null,
title: res.CommonData.Title.value || null,
description: res.CommonData.Description.value || null,
type: res.CommonData.Type || null,
released: null,
manufacturer: null,
howUnlock: null,
}, ],
};
agg.push(formattedReward);
return agg;
}, []);
}
);
return formattedRewards;
};
const mockExpectedResult: ProgressionRewards = {
locked: false,
level: null,
difficulty: ChallengeLevel.Easy,
date: '',
rewardAttachments: [{
image: 'media-image-path',
title: 'MIA',
description: 'reach-mia',
type: 'ArmorVisor',
released: null,
manufacturer: null,
howUnlock: null,
}, ],
};
fit('free rewards to return an array of rewards', async () => {
const awards: ProgressionRewards = await getAllRewards();
expect(awards).toBe([
mockExpectedResult,
mockExpectedResult,
mockExpectedResult,
]);
});
I have tried to simplify your code and the issue in the reduce. I have replace the reduces with filters and maps. Please check this out and let me know if this would help.
const mockScheduledOperation = {
Ranks: [{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
},
{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
},
{
FreeRewards: {
InventoryRewards: [{
InventoryItemPath: 'Inventory/Armor/Visors/012-001-reach-c09fa0b7.json',
}, ],
},
}
]
};
const getAllRewards = async () => {
const freeRewardsInventory =
([] as string[])
// converting multi-dimensional array into uni-dimensional
.concat(
...mockScheduledOperation.Ranks
.filter(rank => rank.FreeRewards.InventoryRewards.length)
.map(rank => (
rank.FreeRewards.InventoryRewards
// removing all falsy values
.filter(Boolean)
.map(item => item.InventoryItemPath)
)
)
);
const getItem = (rewardPath: string) => mockReturnedItem;
const freeRewardsRaw = await Promise.all(freeRewardsInventory.map(rewardPath => getItem(rewardPath)))
const formattedRewards = freeRewardsRaw
.map < ProgressionRewards[] > ((res) => {
const formattedReward: ProgressionRewards = {
// free = unlocked, paid = locked
locked: false,
level: null,
difficulty: res.CommonData.Quality || null,
date: res.CommonData.DateReleased.ISO8601Date || null,
rewardAttachments: [{
image: res.CommonData.DisplayPath.Media.MediaUrl.Path || null,
title: res.CommonData.Title.value || null,
description: res.CommonData.Description.value || null,
type: res.CommonData.Type || null,
released: null,
manufacturer: null,
howUnlock: null,
}, ],
};
return formattedReward;
}, []);
}
);
return formattedRewards;
};

Firestore bulk add field to array

I am struggling to add a field to an map in an array. I am trying to add "canAssist": false to each map in the array for each of the countries.
Here is my database:
[
{
"Afghanistan": {
"country": "Afghanistan",
"countryCode": "AF",
"countryCodeAlt": "AFG",
"emoji": "🇦🇫",
"packages": [
{
"name": "Luxury Couple",
"cost": "$2000.00",
// I want to add canAssist:false here!
},
{
"name": "Quick Retreat",
"cost": "$1000.00",
// I want to add canAssist:false here!
}
]
}
},
{...}
{...}
]
This is what I've tried:
let travelData = database.collection('countries').doc(docName);
travelData.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(array) {
packages.map(package => {
return package.add({
canAssist: false
});
})
});
});
You can use Object.values() and object destructuring to achieve this.
const querySnapshot = [
{
Afghanistan: {
country: 'Afghanistan',
countryCode: 'AF',
countryCodeAlt: 'AFG',
emoji: '🇦🇫',
packages: [
{
name: 'Luxury Couple',
cost: '$2000.00',
// I want to add canAssist:false here!
},
{
name: 'Quick Retreat',
cost: '$1000.00',
// I want to add canAssist:false here!
},
],
},
},
{
...
},
{
...
},
];
const updateSnapshot = (snapshot, newData) => {
return snapshot.map(countryData => {
// only one field with the name of the country
const country = Object.values(countryData)[0];
let updatedCountry = { ...country };
const field = country[newData.field];
if (field) {
if (typeof field === 'string') {
updatedCountry[newData.field] = newData.values;
} else if (Array.isArray(field)) {
updatedCountry[newData.field] = field.map(data => ({ ...data, ...newData.values }));
}
}
return { [updatedCountry.country]: updatedCountry };
});
};
(() => {
console.log('Original', JSON.stringify(querySnapshot, null, 4));
const updatedSnapshot = updateSnapshot(querySnapshot, { field: 'packages', values: { canAssist: false } });
console.log('Updated', JSON.stringify(updatedSnapshot, null, 4));
const updatedSnapshot2 = updateSnapshot(querySnapshot, { field: 'emoji', values: '🇪🇸' });
console.log('Spanish!', JSON.stringify(updatedSnapshot2, null, 4));
})();
Of course, you don't need to have that dynamism with the 'newData', I just added in case you want to play around any field of your datasource.

Categories