How to get actual keys from MongoDB result array? - javascript

INPUT:
let array =[
{name:"xyz", email:"xyz#gmail.com", date:"22/10/2020" },
{name:"abc", email:"abc#gmail.com", date:"29/12/2020" },
{name:"efg", email:"efg#gmail.com", date:"20/01/2021" },
{name:"pqr", email:"pqr#gmail.com", date:"12/08/2020", age:"20" },
{name:"stu", email:"stu#gmail.com", date:"19/09/2020", age:"21" },
]
After performing certain operations I got the above array of objects as output from mongodb collection. From that array I want to get all keys and compare each and every object in an array and if any property present in any object not there in another object then I want to assign the property with empty string value.
To perform that operation I have written the code as shown below-
const keys = array.reduce(
(acc, curr) => (Object.keys(curr).forEach((key) => acc.add(key)), acc),
new Set()
);
const output = array.map((item) =>
[...keys].reduce((acc, key) => ((acc[key] = item[key] ?? ""), acc), {})
);
By performing above operations along with my original keys I am getting unnecessary keys like "$__", "$isNew", "_doc"
MY OUTPUT:
[
{
"$__": {
"activePaths": {
"paths": {
"_id": "init"
},
"states": {
"ignore": {},
"default": {},
"init": {
"_id": true
},
"modify": {},
"require": {}
},
"stateNames": [
"require",
"modify",
"init",
"default",
"ignore"
]
},
"strictMode": false,
"skipId": true,
"selected": {},
"fields": {},
"exclude": null
},
"$isNew": false,
"_doc": {
"_id": "62e6791b049e103f612f0882",
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/8/2020",
"age": "20",
},
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/8/2020",
"age": "20",
},
.
.
.
.
EXPECTED OUTPUT:
[
{
"name": "xyz",
"email": "xyz#gmail.com",
"date": "22/10/2020",
"age": ""
},
{
"name": "abc",
"email": "abc#gmail.com",
"date": "29/12/2020",
"age": ""
},
{
"name": "efg",
"email": "efg#gmail.com",
"date": "20/01/2021",
"age": ""
},
{
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/08/2020",
"age": "20"
},
{
"name": "stu",
"email": "stu#gmail.com",
"date": "19/09/2020",
"age": "21"
}
]
If I am using same code for normal array instead of resultant array from mongoodb I am getting correct output.
Please help me in resolving the above issue.

Query
if you have few fields and you know their names you can do it on server like bellow, in simple way
check if field (if missing it will be false) if its there keep old value, else add it with ""
the bellow doesn't work with boolean fields, if you have those you should check if type="missing" but in your case you dont have boolean fields so it will be ok
Playmongo
aggregate(
[{"$set":
{"name": {"$cond": ["$name", "$name", ""]},
"email": {"$cond": ["$email", "$email", ""]},
"date": {"$cond": ["$date", "$date", ""]},
"age": {"$cond": ["$age", "$age", ""]}}}])

Related

How to sort json array having groups of json objects

I want to sort the below json array based on the name attribute. The challenge is if the "rows" contain two json array element then it should first short within the group and then sort based on the other json array.
Here is my attempt. It is sorting the array but not the (elements inside the group)
// sort the data
this.leadPoolRecords = JSON.parse(
JSON.stringify(this.leadPoolRecords)
).sort((a, b) => {
a = a[colName] ? a[colName].toLowerCase() : ""; // Handle null values
b = b[colName] ? b[colName].toLowerCase() : "";
return a > b ? 1 * isReverse : -1 * isReverse;
});
data = [
{
"button": {
"btn": true,
"size": "20"
},
"rows": [
{
"name": "john",
"role": "CEO",
"phone": "xxxxxxxxx",
"email": "bcd#email.com"
}
]
},
{
"button": {
"btn": true,
"size": "20"
},
"rows": [
{
"name": "Mike",
"role": "Director",
"phone": "xxxxxxxxx",
"email": "cde#email.com"
}
]
},
{
"button": {
"btn": true,
"size": "20"
},
"rows": [
{
"name": "rahul",
"role": "CTO",
"phone": "xxxxxxxxx",
"email": "xyz#email.com"
},
{
"name": "ajay",
"role": "Researcher",
"phone": "xxxxxxxxx",
"email": "abc#email.com"
}
]
}
]
First, you can sort the rows arrays this way:
data.forEach(item => item.rows.sort((row1, row2) => row1.name.localeCompare(row2.name)));
Then you can sort the elements of data based on the rows arrays. For example, if you want to sort them based on the name of the first row:
data.sort((item1, item2) => item1.rows[0].name.localeCompare(item2.rows[0].name));

How to enhance a json object?

I am recieving a json object from an api as following:
[
{"id":998,
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"membership":{"type":"Semi-Annually","price":18000},
"start_date":"2019-11-19","end_date":"2020-05-16","payment":12000,"balance":0
},
{"id":1004,
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"membership":{"type":"Annually","price":30000},
"start_date":"2020-08-27","end_date":"2021-08-27","payment":30000,"balance":5000,
}
]
in angular when I loop to print the data 'client' information prints two times, because it is repeated two times.
<div *ngFor="let c of clientinfo">
{{c.client.name}}
{{c.membership.type}}
{{c.membership.price}}
{{c.start_date}}
{{c.end_date}}
.
.
.
</div>
How can I enhance this data so I get only client information once but the rest stay as they are?
thanks in advance
Whenever you need to group some data by some value you can use an object because object properties are guaranteed to never be duplicated. You have to be careful however because properties can be overwritten.
First, let's settle on a structure that works. The following is one such structure that can work:
{
[client.id] : {
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
[client.id] : {
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
..
}
There are other ways to arrange the data but the key is to exploit objects to implement a map/hash/associative array of key/value pairs. With this we can group the data from your array:
let group = {};
jsonData.forEach(x => {
// check if group already contain this client:
if (!group[x.client.id]) {
// auto-create array if does not exist
group[x.client.id] = {
client: x.client,
info: []
};
}
group[x.client.id].info.push({
membership: x.membership,
start_date: x.start_date
});
});
Now you have an object grouped by client id where each property is an object that has an info array that contains membership information.
If you need to loop over this data structure you can convert it back to an array by doing:
let groupArray = Object.values(group);
This will give you the following data structure:
[
{
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
{
client: client,
info : [
{ membership, start_date },
{ membership, start_date },
..
]
},
..
]
An array of client objects with an info property containing an array of membership data. For your sample data it would be something like:
[
{
"client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123},
"info": [
{
"membership":{"type":"Semi-Annually","price":18000},
"start_date":"2019-11-19",
"end_date":"2020-05-16",
"payment":12000,"balance":0
},
{
"membership":{"type":"Annually","price":30000},
"start_date":"2020-08-27",
"end_date":"2021-08-27",
"payment":30000,"balance":5000,
}
]
}
]
You need to create array of memberships for each client like below. And in the template file, you need to use two *ngFor loops. One to loop client details and another one to loop the respective client's membership details.
Working stackblitz
const result = [{
"id": 998,
"client": {
"id": "AF01072",
"name": "Vivek",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Semi-Annually",
"price": 18000
},
"start_date": "2019-11-19",
"end_date": "2020-05-16",
"payment": 12000,
"balance": 0
},
{
"id": 1004,
"client": {
"id": "AF01072",
"name": "Vivek",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Annually",
"price": 30000
},
"start_date": "2020-08-27",
"end_date": "2021-08-27",
"payment": 30000,
"balance": 5000,
},
{
"id": 1005,
"client": {
"id": "AF01073",
"name": "Some Other",
"lastName": "Joshi",
"phone": 123
},
"membership": {
"type": "Annually",
"price": 30000
},
"start_date": "2020-08-27",
"end_date": "2021-08-27",
"payment": 30000,
"balance": 5000,
}
].reduce((acc, item, i) => {
if (i == 0) {
acc.push(constructCorrectObject(item));
return acc;
}
let foundItem = acc.find(it => it.id === item.client.id);
if (foundItem) {
addMemeberShipDetails(foundItem, item);
return acc;
} else {
acc.push(constructCorrectObject(item));
return acc;
}
}, []);
function constructCorrectObject(item) {
return {
"id": item.client.id,
"name": item.client.name,
"lastName": item.client.lastName,
"phone": item.client.phone,
"membership": [{
"id": item.id,
"type": item.membership.type,
"price": item.membership.price,
"start_date": item.start_date,
"end_date": item.end_date,
"payment": item.payment,
"balance": item.balance,
}]
}
}
function addMemeberShipDetails(acc, item) {
acc.membership.push({
"id": item.id,
"type": item.membership.type,
"price": item.membership.price,
"start_date": item.start_date,
"end_date": item.end_date,
"payment": item.payment,
"balance": item.balance,
});
}
console.log(result);

Sorting a nest object by datetime not working as expected

I am having some trouble sorting a nested object by its timestamp. I was hoping for some help...
This is what the object looks like and what I have so far...
useEffect(() => {
if (realtime.length) {
let unorderedmessage = realtime.concat(messages);
const orderedMessages = unorderedmessage
.slice()
.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
setMessages(orderedMessages);
}
}, [realtime]);
[
Object {
"_id": "a16edcb7-17e1-46ea-b8ce-5ec312d5eb6c",
"createdAt": 2020-04-23T01:51:48.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "2–> Olivia to Mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "5ef28d42-6f7c-45eb-a5e1-59ca700f56b7",
"createdAt": 2020-04-23T02:01:52.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "4–> Olivia to mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "1e07873f-f010-4e9d-be17-9bcb7793695b",
"createdAt": 2020-04-23T02:02:06.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"lTONqS9O00PhkxwHD2EYs05EMwu2",
],
"text": "5–> mike to Olivia",
"user": Object {
"_id": "OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
"avatar": "123",
},
},
Object {
"_id": "5fecafc3-c608-4156-b88c-f6c57e8e9977",
"createdAt": 2020-04-23T02:01:20.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "3–> Olivia to Mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "fae07391-9968-432a-8a39-0c1be0d7e9ac",
"createdAt": 2020-04-23T01:51:41.000Z,
"index": 0,
"key": "cid-1710824786",
"receiver": Array [
"lTONqS9O00PhkxwHD2EYs05EMwu2",
],
"text": "1–> mike to Olivia",
"user": Object {
"_id": "OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
"avatar": "123",
},
},
],
The messages are still coming in out of order so I am sure I am writing the sort function incorrectly. I am going through these tutorials and docs and it seems to be correct....
https://www.geeksforgeeks.org/sort-an-object-array-by-date-in-javascript/
https://flaviocopes.com/how-to-sort-array-by-date-javascript/
How to sort an array by a date property
I have also tried explicitly writing out the function like:
let unorderedmessage = realtime.concat(messages);
unorderedmessage.sort(function(a, b) {
return new Date(b.createdAt) - new Date(a.createdAt);
});
setMessages(unorderedmessage);
but still no luck. Can anyone see what I am doing wrong?
Works like a charm for me: https://playcode.io/583725/
Cannot be the issue in your Object variable definition?
You don't need to specify Object, this is enough:
const myNewObject = {firstKey: 'firstValue', secondKeys: 'secondValue'}
But if you do, you have to create it with new keyword:
const myNewObject = new Object {firstKey: 'firstValue', secondKeys: 'secondValue'}

Delete duplicate value from array of array

I have an object array and I want to avoid to duplicate value with a specific key value.
This is an objectArray.
var dept =
[
{
"department": [
{ "userName": "cds",
"userId": "33",
"userFirstname": "Chef",
"userLastname": "Jone"
},
{
"userName": "asset1",
"userId": "27",
"userFirstname": "Asset",
"userLastname": "Ann "
}
],
"comment": "",
"doc": null
},
{
"department": [
{
"userName": "audit1",
"userId": "32",
"userFirstname": "Audit",
"userLastname": "Kim"
},
{ "userName": "cds",
"userId": "33",
"userFirstname": "Chef",
"userLastname": "Jone"
}
],
"comment": "",
"doc": null
}
];
I tried to return the unduplicated object by javascript.
But the result seems different.
I can return the value from one object array. However, I feel difficulties to extract the values from array of array.
How to assign a filter array of an array?
Any help would be appreciated.
Thanks in advance.
function getUnique(dept, comp) {
const unique = dept
.map(e => e[comp])
// store the keys of the unique objects
.map((e, i, final) => final.indexOf(e) === i && i)
// eliminate the dead keys & store unique objects
.filter(e => dept[e]).map(e => dept[e]);
return unique;
}
return getUnique(dept,'userName');
I would get the result
[
{
"department": [
{ "userName": "cds",
"userId": "33",
"userFirstname": "Chef",
"userLastname": "Jone"
},
{
"userName": "asset1",
"userId": "27",
"userFirstname": "Asset",
"userLastname": "Ann "
}
],
"comment": "",
"doc": null
},
{
"department": [
{
"userName": "audit1",
"userId": "32",
"userFirstname": "Audit",
"userLastname": "Kim"
}
],
"comment": "",
"doc": null
}
];
However, I got the result
[
{
"department": [
{ "userName": "cds",
"userId": "33",
"userFirstname": "Chef",
"userLastname": "Jone"
},
{
"userName": "asset1",
"userId": "27",
"userFirstname": "Asset",
"userLastname": "Ann "
}
],
"comment": "",
"doc": null
}
]
You can use a combination of map and filter
var dept =[{"department": [{ "userName": "cds","userId": "33","userFirstname": "Chef","userLastname": "Jone"},{"userName": "asset1","userId": "27","userFirstname": "Asset","userLastname": "Ann "}],"comment": "","doc": null},{ "department": [{ "userName": "audit1","userId": "32","userFirstname": "Audit","userLastname": "Kim"},{ "userName": "cds","userId": "33","userFirstname": "Chef","userLastname": "Jone"}],"comment": "","doc": null}];
let tracker = {}
let op = dept.map(val => {
let department = val.department
let filtered = department.filter(({userId}) => {
if(tracker[userId] !== undefined ){
return false
} else {
tracker[userId] = userId
return true
}
})
return {...val,department: filtered}
})
console.log(op)

Need help in lodash combinations to get the below object

Below is my object First step is to check the socialAuth array of objects and get the platformName which has the showStats value as false.
I have accomplished the step1 as below
var arrList2 = _.pluck(_.where(creatorObj.socialAuth, {'showStats': false}), "platformName");
['Twitter'] is the output of the arrList2
var creatorObj =
{
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [
{
"reach": 205976,
"_id": "asdfasdfasdf",
"profileUrl": null,
"engagements": 126,
"platformName": "Twitter"
}
],
"socialAuth": [
{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
},
{
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}
]
};
Second step is to check the above arrList2 with the sociaStats array and remove the value from it and print the object again.
I need help in this second step.
I need the resulting object as
var creatorObj =
{
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [],
"socialAuth": [
{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
},
{
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}
]
};
You need to use _.remove() to remove the elements from array based on your condition.
Demo
var creatorObj = {
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [{
"reach": 205976,
"_id": "asdfasdfasdf",
"profileUrl": null,
"engagements": 126,
"platformName": "Twitter"
}],
"socialAuth": [{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
}, {
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}]
};
var arrList2 = _.pluck(_.where(creatorObj.socialAuth, {
'showStats': false
}), "platformName");
creatorObj.socialStats = _.remove(creatorObj.socialStats, function(n) {
return !_.includes(arrList2, n.platformName);
});
console.log(creatorObj);
document.write(JSON.stringify(creatorObj));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

Categories

Resources