How to increment nested objects with variable names in MongoDB - javascript

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);

Related

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"}
// ];
//+=====================================+

Dynamically create array of objects, from array of objects, sorted by an object property

I'm trying to match and group objects, based on a property on each object, and put them in their own array that I can use to sort later for some selection criteria. The sort method isn't an option for me, because I need to sort for 4 different values of the property.
How can I dynamically create separate arrays for the objects who have a matching property?
For example, I can do this if I know that the form.RatingNumber will be 1, 2, 3, or 4:
var ratingNumOne = [],
ratingNumTwo,
ratingNumThree,
ratingNumFour;
forms.forEach(function(form) {
if (form.RatingNumber === 1){
ratingNumOne.push(form);
} else if (form.RatingNumber === 2){
ratingNumTwo.push(form)
} //and so on...
});
The problem is that the form.RatingNumber property could be any number, so hard-coding 1,2,3,4 will not work.
How can I group the forms dynamically, by each RatingNumber?
try to use reduce function, something like this:
forms.reduce((result, form) => {
result[form.RatingNumber] = result[form.RatingNumber] || []
result[form.RatingNumber].push(form)
}
,{})
the result would be object, with each of the keys is the rating number and the values is the forms with this rating number.
that would be dynamic for any count of rating number
You could use an object and take form.RatingNumber as key.
If you have zero based values without gaps, you could use an array instead of an object.
var ratingNumOne = [],
ratingNumTwo = [],
ratingNumThree = [],
ratingNumFour = [],
ratings = { 1: ratingNumOne, 2: ratingNumTwo, 3: ratingNumThree, 4: ratingNumFour };
// usage
ratings[form.RatingNumber].push(form);
try this its a work arround:
forms.forEach(form => {
if (!window['ratingNumber' + form.RatingNumber]) window['ratingNumber' + form.RatingNumber] = [];
window['ratingNumber' + form.RatingNumber].push(form);
});
this will create the variables automaticly. In the end it will look like this:
ratingNumber1 = [form, form, form];
ratingNumber2 = [form, form];
ratingNumber100 = [form];
but to notice ratingNumber3 (for example) could also be undefined.
Just to have it said, your solution makes no sense but this version works at least.
It does not matter what numbers you are getting with RatingNumber, just use it as index. The result will be an object with the RatingNumber as indexes and an array of object that have that RatingNumber as value.
//example input
var forms = [{RatingNumber:5 }, {RatingNumber:6}, {RatingNumber:78}, {RatingNumber:6}];
var results = {};
$.each(forms, function(i, form){
if(!results[form.RatingNumber])
results[form.RatingNumber]=[];
results[form.RatingNumber].push(form);
});
console.log(results);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HIH
// Example input data
let forms = [{RatingNumber: 1}, {RatingNumber: 4}, {RatingNumber: 2}, {RatingNumber: 1}],
result = [];
forms.forEach(form => {
result[form.RatingNumber]
? result[form.RatingNumber].push(form)
: result[form.RatingNumber] = [form];
});
// Now `result` have all information. Next can do something else..
let getResult = index => {
let res = result[index] || [];
// Write your code here. For example VVVVV
console.log(`Rating ${index}: ${res.length} count`)
console.log(res)
}
getResult(1)
getResult(2)
getResult(3)
getResult(4)
Try to create an object with the "RatingNumber" as property:
rating = {};
forms.forEach(function(form) {
if( !rating[form.RatingNumber] ){
rating[form.RatingNumber] = []
}
rating[form.RatingNumber].push( form )
})

Problems in accessing sub properties from separate JavaScript file

I was trying to access sub-properties from a javascript file and it's giving me something weird!
Suppose this is my JS file named data.js
module.exports = {
something: {
name: "Something",
num: 1,
email: "something#gmail.com"
},
somethingtwo: {
name: "Something Something",
num: 2,
email: "somethingtwo#gmail.com"
},
};
In my main js file named app.js, where I need to access it, it looks like
var persons = require('./data.js');
var getAName = function() {
for(var name in persons) {
console.log(name.email);
}
}
I really don't know what goes wrong but I have been trying this for quite a long time now. The expected output is the email Ids from the data.js file but instead, i get undefined times the number of entries (if there are 2 entries in data.js, then I get 2 undefine and so on).
How can I access the email or the num from the data.js without those undefines?
console.log(name) is returning something somethingtwo
Well, name.email is undefined because name is a string.
You can test that by writing
console.log(typeof name);
Now, to solve your problem, you need to access the property correctly:
var getAName = function() {
for (var name in persons) {
console.log(persons[name].email)
}
}
Returns:
something#gmail.com
somethingtwo#gmail.com
for(var name in persons) {
//persons is actually an object not array
//you are actually iterating through keys of an object
//var name represent a key in that object
console.log(persons[name]); //value corresponding to the key
}
I guess this code will give you the desired result.
You should be using console.log(persons[name].email)
require don't automatically calls the module
var DataArchive = require('./data.js');
var module = DataArchive.module;
var persons = module.exports;
var getAName = function() {
for(var person in persons) {
//person should be something (first iteration) and somethingtwo (second iteration)
console.log(person.email);
}

javascript dynamic structure with array or object

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.

How can i send objects as parameter Javascript

I need to pass an array as parameter but i have a problem, i dont know how to explain it so here is the example:
I have this code:
var doc = document;
var Class = {};
Class.Validate = function(opc)
{
alert(opc.id);//
return Class;// when returns the object the alert trigger as expected showing "#name"
};
Class.Validate({
id: "#name",
})
But what im trying to do is this:
var Class = {};
Class.Validate = function(opc)
{
alert(opc.name);//when the object is return show display "carlosmaria"
return Class;//
};
Class.Validar({
name: {field:"carlos",field:"maria"},
})
how can i archived that?
alert(opc.name) should return something like {Object object} because it's an objet. The second point is that your object has twice "field" as property.
If you want to use an array, you should call this way:
Class.Validar({
name: ["carlos", "maria"]
})
Then, you could loop over opc.name to concatenate a full name. Something like this:
Class.Validate = function(opc)
{
var name = "";
for (var i=0, len=opc.name.length; i<len; ++i) {
name += opc.name[i];
}
alert(name);//when the object is return show display "carlosmaria"
return Class;//
};
Consider using actual arrays (via array literals):
Class.Validate({
name: ["carlos", "maria"]
});

Categories