javascript dynamic structure with array or object - javascript

Im trying to create a structure with Javascript as follows:
var users = {
user.id: {
session.id1: session.id1,
session.id2: session.id2,
session.id3: session.id3
},
user.id2: {
session.id1: session.id1,
session.id2: session.id2,
session.id3: session.id3
},
};
What i need: add new sessions and remove them, removing okay, but how should i define object and how can i push new sessions to user obejct? That's why key is equal to value.

If you want to use session.id1 instead of something like sessionId1 :
Assign value:
users['user.id'].['session.id1'] = value;
Create object:
var users = {
'user.id': {
'session.id1': session.id1,
'session.id2': session.id2,
'session.id3': session.id3
},
'user.id2': {
'session.id1': session.id1,
'session.id2': session.id2,
'session.id3': session.id3
},
};
But I don't recommend it. If you are the only one who is gonna work with this code, it's ok.

You can first create an empty object and fill it as and when the data comes like
users[user.id] = {};
For an example:
var users = {};
var user = {id : 1}; //Data received(Just an example)
users[user.id] = {};
var session = {id1 : 1.1}; //Data received
users[user.id][session.id1] = session.id1;
console.log(JSON.stringify(users));

How about refactoring the user object to store sessions as an array and push, pop and slice them as required.
var users = [
{
id:'userid',
sessions: [
{
id: 'sessionid',
sessiondata: something
},
{
id: 'sessionid',
sessiondata: something
}
]
}];
This way to can just use normal array operators on the session array for each user.

Related

How to alter an item in an object using JavaScript to replace special characters that are not accepted by Firebase

I am trying to push some Kubernetes stats to my Firebase Real-time Database (not Firestore) and due to the special character "/" in the keys, Firebase is throwing an error. I tried to search for similar issues here but they are not quite similar to mine (tried so many replace or even delete functions but did not work). Here are my objects:
=====>> THE OBJECT
So i want to change the "/" to something like "-" on order to be able to push the entire object as to Firebase.
Example:
beta.kubernetes.io/arch --> beta.kubernetes.io-arch
beta.kubernetes.io/os --> beta.kubernetes.io-os
kubernetes.io/hostname --> kubernetes.io-hostname
node-role.kubernetes.io/master --> node-role.kubernetes.io-master
Please note that i have to process this in the attached object screenshot. So i have to process this: k8snodes{obj} -> items[arr] -> metadata{obj} -> labels{obj} in order to reach the keys i want to replace, and then push the entire object (k8snodes) to firebase.
I am using Javascript/NodeJS. thank you so much.
This is how you do it according to your data structure.
.reduce() reference: reduce
var k8snodes = {
items: [
{
"metadata": {
"labels": {
"beta.kubernetes.io/arch": "amd",
"beta.kubernetes.io/os": "linux"
}
}
},
{
"metadata": {
"labels": {
"kubernetes.io/hostname": "centos-master-node",
"node-role.kubernetes.io/master": "master"
}
}
}
]
}
k8snodes.items.forEach(function(data){
var newK8snodes = Object.keys(data.metadata.labels).reduce((total,currentValue) => {
var newLabelKey = currentValue.replace(/\//g,'-')
var newLabel = {[newLabelKey]: data.metadata.labels[currentValue]}
total = {...total, ...newLabel}
return total;
}, {});
data.metadata.labels = newK8snodes
});
console.log(k8snodes);
another simple solution is
var a = 'beta.kubernetes.io/arch';
console.log(a.replace('/','-'))
const ob = {
'beta.kubernetes.io/arch': 'amd',
'beta.kubernetes.io/os': 'linux',
'kubernetes.io/hostname': 'centos',
'node-role.kubernetes.io/master': 'master'
}
const newOb = {};
for(var i in ob) {
const newKey = i.replace(/\//g,'-')
newOb[newKey] = ob[i];
}
console.log(newOb);

Mapping data with dynamic variables

I am having a little trouble trying to achieve something. So I have some data
let data = [
{
"ID": 123456,
"Date": "2012-01-01",
"Irrelevant_Column_1": 123,
"Irrelevant_Column_2": 234,
"Irrelevant_Column_3": 345,
"Irrelevant_Column_4": 456
},
...
]
And I wanted to remove the irrelevant columns. So someone suggested using map
data = data.map(element => ({ID: element.ID, Date: element.Date}))
The problem is, I dont want to define the columns. I have the user select the columns to keep, and assign them to a variable. I can then do something like
let selectedId = this.selectedIdCol;
The issue is, I am unable to now use this within the map. I am trying
let selectedId = this.selectedIdCol;
this.parsed_csv = data.map(element => (
{ID: element.selectedId, Date: element.Date}
));
But that does not seem to work, just returns the date. Also, my IDE is saying that the variable is unused. So how can I use the selectedId variable as part of the map function?
Thanks
You can do using Bracket notation notation and helper function
Whenever you want to use variable to access property you need to use [] notation.
let data = [{"ID": 123456,"Date": "2012-01-01","column_1": 123,"column_2": 234,"column_3": 345,"column_4": 456},{"ID": 123456,"Date": "2018-10-01", "column_1": 123,"column_2": 234,"column_3": 345,"column_4": 46},]
function selectDesired(data,propName1,propName2){
return data.map(e=> ({[propName1]: e[propName1], [propName2]: e[propName2]}))
}
console.log(selectDesired(data, 'Date', 'column_4'))
The basic technique is illustrated here, assuming that the user's selected column_name is "ID"
let data = [
{
"ID": 123456,
"Date": "2012-01-01",
"Irrelevant_Column_1": 123,
"Irrelevant_Column_2": 234,
"Irrelevant_Column_3": 345,
"Irrelevant_Column_4": 456
}
];
let column_name = "ID";
let curated = data.map(element=>({[column_name]: element[column_name]}));
console.log(curated)
If you are wanting the user to be able to multi-select their columns,(assuming data from above is still in scope)
let user_selection = ["ID","Date"];
let curated = data.map(
(element)=>
{
let item = {};
user_selection.forEach(
(property)=>
{
item[property] = element[property];
}
return item;
}
);
To set up a function that can handle multiple calling situations without having a monstrously hack-and-patched source history, set up the function's signature to receive a spread list of properties.
If you wish to extend the capabilities to accept
a csv property list
an array of property names delivered directly
an array of property names
you can assume the properties argument in the signature to be an iterable of property groupings, having the most basic grouping be a singleton.
Commentary embedded within the sample code to expound in more detail
var getProjection = (data,...properties) =>
{
//+=================================================+
// Initialize the projection which will be returned
//+=================================================+
let projection = {};
//+=================================================+
// Set up the property mapping func
//+=================================================+
let safe_assign = (source, target ,propertyDesignator)=>
{
if(source[propertyDesignator])
{
target[propertyDesignator] = source[propertyDesignator];
}
};
//+=====================================================+
// Iterate the properties list, assuming each element to
// be a property grouping
//+=====================================================+
properties.forEach(
(propertyGroup)=>
{
//+-----------------------------------------------+
// If the propertyGroup is not an array, perform
// direct assignment
//+-----------------------------------------------+
if(!Array.isArray(propertyGroup))
{
//+-------------------------------------------+
//Only map the requested property if it exists
//+-------------------------------------------+
safe_assign(data,projection,propertyGroup);
}
//+-----------------------------------------------+
// If the propertyGroup *is* an array, iterate it
// This technique obviously assumes that your
// property groupings are only allowed to be one
// level deep. This is for accommodating distinct
// calling conventions, not for supporting a deeply
// nested object graph. For a deeper object graph,
// the technique would largely be the same, but
// you would need to recurse.
//+-----------------------------------------------+
if( Array.isArray(propertyGroup))
{
propertyGroup.forEach(
(property)=>
{
safe_assign(data,projection,property);
}
}
}
);
//+===================================+
// Return your projection
//+===================================+
return projection;
};
//+--------------------------------------+
//Now let's test
//+--------------------------------------+
let data = [
{ID:1,Foo:"Foo1",Bar:"Bar1",Baz:"Inga"},
{ID:2,Foo:"Foo2",Bar:"Bar2",Baz:"Ooka"},
{ID:3,Foo:"Foo3",Bar:"Bar3",Baz:"oinga",Floppy:"Floop"},
{ID:4,Foo:"Foo4",Good:"Boi",Bar:"Bar3"Baz:"Baz"}
];
//***************************************
//tests
//***************************************
var projection1 = getProjection(data.find(first=>first),"ID","Baz"));//=>{ID:1,Baz:"Inga"}
var projection2 = getProjection(data[0],["ID","Baz"]);//=>{ID:1,Baz:"Inga"}
var projection3 = getProjection(data[0],...["ID","Baz"]);//=>{ID:1,Baz:"Inga"}
var user_selected_properties = ["ID","Good","Baz"];
var projections = data.map(element=>getProjection(element,user_selected_properties));
//+=====================================+
// projections =
// [
// {ID:1,Baz:"Inga"},
// {ID:2,Baz:"Ooka"},
// {ID:3,Baz:"oinga"},
// {ID:4,Good:"Boi",Baz:"Baz"}
// ];
//+=====================================+

How to increment nested objects with variable names in MongoDB

So the code I'd 'like' to work is below. I have a variable name as the name of the key of the object unread, which seems to be in the only way of doing this in MongoDB is by creating an object outside and referencing it as the value for $inc. This doesn't seem to work, it does work however if I just have a key partnerId without nesting the object. My question is how do i get it working with nested objects.
Does work:
var partnerId = 234567;
var action = {
unread: {}
};
action[partnerId] = 1;
Threads.update(Session.get('currentChat'),
{
$inc: action
}, callback);
Does not work, but would like it to work:
var partnerId = 234567;
var action = {
unread: {}
};
action.unread[partnerId] = 1;
Threads.update(Session.get('currentChat'),
{
$inc: action
}, callback);
I get an error about not being able to increment things that aren't numbers, which I guess is refering to the object within the object.
The schema I have is like this, with 123456 and 234567 as user ids and I just want to increment that number:
{
_id: 123,
unread: {
123456: 0,
234567: 1,
}
}
If you wanted to write this out in a non-dynamic way, you'd do:
var id = Session.get('currentChat');
Threads.update(id, {$inc: {'action.unread.234567': 1}});
$inc needs to take an object with a dynamically created key based on partnerId like so:
var partnerId = 234567;
var key = 'action.unread.' + partnerId;
var obj = {};
obj[key] = 1;
Now obj looks like:
{'action.unread.234567': 1}
So we can plug that into your original code:
Threads.update(id, {$inc: obj}, callback);

How to convert a bunch of arrays into a single object?

Here is what im doing:
onClick, grab details immediate subnodes and publish it on html. Status = DONE // This works well
NOW, I am using a bunch of arrays to get this done.
node.eachSubnode(function(node) {
title[title.length] = node.name; // This is what i want to modify
data[data.length] = node.data; // This is what i want to modify
});
Here is how they look currently:
title = ['Coffee', 'Tea'];
data = ["Americans", "Britishers"]; // i use a loop to iterate through these arrays and append to html.
Here is what i want it to be:
var preference = {
title: 'Coffee',
data: 'Americans'
},
{
title: 'Tea',
data: 'Americans
}
I want to create this using the node.eachSubnode loop.
I'm not sure if I understood correctly, but I think this is what you want:
var preferences = [];
node.eachSubnode(function(node) {
preferences.push({
title: node.name,
data: node.data.germ
});
});
You cannot create an object that looks exactly like that, I think you need an array with objects. Assuming your node is an array with the length property, this method is the fastest.
var preference = new Array(node.length||0), i = 0;
node.eachSubnode(function(node) {
preference[i++] = {
title: node.name,
data: node.data.germ
};
});

add property to nested array in mongodb document

I have a mongodb document with the following structure
> db.user.find().limit(1);
{ "_id" : "1", "foo" : { "bars" : [
{
"name" : "bar1"
},
{
"name" : "bar2"
},
], ... }, ... }
I want to add a new property to each bar. I've got my script iterating over the bars array, but I can't get the new property in there, how can I do this?
var users = db.user.find({"foo.bars":{$exists:true}});
users.forEach(function(user) {
user.foo.bars.forEach(function(bar)
{
printjson(bar);
//how can I specify the current 'bar' in this update?
//db.experience.update({_id: user._id}, {$set: {"what goes here?" : "newbarValue"}});
});
});
So says the preacher man:
var users = db.user.find({"foo.bars":{$exists:true}});
users.forEach(function(user) {
var id = user._id;
var foo_bars = user.foo.bars;
var new_foo_bars = [];
for(var i = 0; i < foo_bars.length; i++) {
var foo_bar = foo_bars[i];
foo_bar['newkey'] = 'newvalue';
new_foo_bars.push(foo_bar);
}
db.user.update({"_id":id}, {$set:{"foo.bars":new_foo_bars}});
});
I have noticed that you are scrolling through the array on the client side there in JS.
If you were to form a new "bars" array from the old one then push it in as a whole new value this would mean you only do one DB call and the code is quite elegant.
If MongoDB does not support it normally it is better to just do the work on the client side.
You have to update each element of the nested document individually. Using the positional operator '$' will not work since it will only work on the first match (as documented).

Categories