JS Object Array Remove last empty element - javascript

I have that javascript object :
MyObject = [
{
"name" : "aaa",
"firstname" : "aaaaa"
},
{
"name" : "bbb",
"firstname" : "bbbb"
},
{
"name" : "cccc",
"firstname" : "" <--------- firstname is empty, but the element is not in the last
},
{
"name" : "ddd",
"firstname" : "dddd"
},
{
"name" : "eeee",
"firstname" : "" <--------- firstname is empty
},
{
"name" : "fffff",
"firstname" : "" <--------- firstname is empty
},
]
I want to delete the lastest lines that have "firstname" empty ... (a sort of trim) ... i dont want to remove all lines that have "firstname" empty... but just who are in the latestes lines. (that are in the bottom)
So, the result will be :
MyObject = [
{
"name" : "aaa",
"firstname" : "aaaaa"
},
{
"name" : "bbb",
"firstname" : "bbbb"
},
{
"name" : "cccc",
"firstname" : ""
},
{
"name" : "ddd",
"firstname" : "dddd"
}
]
Thank you

You can pop of at the end of the array as long as the firstname is empty
var MyObject = [{
"name": "aaa",
"firstname": "aaaaa"
}, {
"name": "bbb",
"firstname": "bbbb"
}, {
"name": "cccc",
"firstname": ""
}, {
"name": "ddd",
"firstname": "dddd"
}, {
"name": "eeee",
"firstname": ""
}, {
"name": "fffff",
"firstname": ""
}];
for (var i=MyObject.length;i--;) if (MyObject[i].firstname==="") MyObject.pop(); else break;
console.log(MyObject)
.as-console-wrapper {max-height: 100%!important; top: 0!important;}

Try this:
var MyObject = [
{
"name" : "aaa",
"firstname" : "aaaaa"
},
{
"name" : "bbb",
"firstname" : "bbbb"
},
{
"name" : "cccc",
"firstname" : ""
},
{
"name" : "ddd",
"firstname" : "dddd"
},
{
"name" : "eeee",
"firstname" : ""
},
{
"name" : "fffff",
"firstname" : ""
}
];
var i = MyObject.length;
while(true) {
if (!MyObject[--i].firstname) {
MyObject.pop();
} else {
break;
}
}
console.log(MyObject);

Related

How to Join 2 Collection into 1 in Mongoose without Populate

so I have the task to combine 2 collections into 1 to be able to search by additional parameter queries
like ac_key or ac_value,
but the reality is not as expected, this only works for one collection, when I do a search with the other collection nothing happens
account collection
{
"_id" : ObjectId("5ce2409399c7952d4c6f0f5d"),
"status" : "not verified",
"name" : "Monkey D Garp",
"phone" : "1234",
"email" : "ccc#ccc.com",
"password" : "$2a$10$186wQau8GBtqOORovWP7..r8bwSAW1kK9Cb0lT8ckeNFSkEDYjOuu"
},
{
"_id" : ObjectId("5ce2408b99c7952d4c6f0f5b"),
"status" : "not verified",
"name" : "Monkey D Garp",
"phone" : "1234",
"email" : "aaa#aaa.com",
"password" : "$2a$10$WskmjNldC2TQ13Rl6ZLqROJwIux1KwM2tkCqfbiMSxWKRUAgsQWn."
},
{
"_id" : ObjectId("5ce2407c99c7952d4c6f0f59"),
"status" : "not verified",
"name" : "Monkey D Garp",
"phone" : "1234",
"email" : "bbb#bbb.com",
"password" : "$2a$10$g1WRwu4Tp85hIIyw4ONd9e3CGOd7u8UN1jfF.zsVpAOE9Usdy01Bm"
}
account_meta collection
{
"_id" : ObjectId("5ce37884551b0b07f4b60598"),
"value" : "sleeping",
"key" : "speciality",
"account_id" : ObjectId("5ce2407c99c7952d4c6f0f59")
},
{
"_id" : ObjectId("5ce240fc99c7952d4c6f0f61"),
"value" : "cooking",
"key" : "hobby",
"account_id" : ObjectId("5ce2407c99c7952d4c6f0f59")
},
{
"_id" : ObjectId("5ce240f399c7952d4c6f0f60"),
"value" : "12",
"key" : "age",
"account_id" : ObjectId("5ce2407c99c7952d4c6f0f59")
},
{
"_id" : ObjectId("5ce240e799c7952d4c6f0f5f"),
"value" : "singapore",
"key" : "address",
"account_id" : ObjectId("5ce2407c99c7952d4c6f0f59")
},
{
"_id" : ObjectId("5ce2409399c7952d4c6f0f5e"),
"value" : "staff",
"account_id" : ObjectId("5ce2409399c7952d4c6f0f5d"),
"key" : "role"
},
{
"_id" : ObjectId("5ce2408b99c7952d4c6f0f5c"),
"value" : "user",
"account_id" : ObjectId("5ce2408b99c7952d4c6f0f5b"),
"key" : "role"
},
{
"_id" : ObjectId("5ce2407c99c7952d4c6f0f5a"),
"value" : "admin",
"account_id" : ObjectId("5ce2407c99c7952d4c6f0f59"),
"key" : "role"
}
expected output
[{
"status": "not verified",
"_id": "5ce2407c99c7952d4c6f0f59",
"name": "Monkey D Garp",
"phone": "1234",
"email": "bbb#bbb.com",
"password": "$2a$10$g1WRwu4Tp85hIIyw4ONd9e3CGOd7u8UN1jfF.zsVpAOE9Usdy01Bm",
"role": "admin",
"address": "singapore",
"age": "12",
"hobby": "cooking",
"speciality": "sleeping"
}]
the condition: I want to find the key and value with the parameters ac_key and ac_value, when I look for non-specific and related data it will not appear, and get all the meta related to the same account_id
assuming data to merge from account to meta account exists _id (account) = account_id (account_meta)
in reality when i hit ac_key: age, and ac_value: '12', i get:
[
{
"status": "not verified",
"_id": "5ce2407c99c7952d4c6f0f59",
"name": "Monkey D Garp",
"phone": "1234",
"email": "bbb#bbb.com",
"password": "$2a$10$g1WRwu4Tp85hIIyw4ONd9e3CGOd7u8UN1jfF.zsVpAOE9Usdy01Bm",
"role": "admin",
"address": "singapore",
"age": "12",
"hobby": "cooking",
"speciality": "sleeping"
},
{
"status": "not verified",
"_id": "5ce2408b99c7952d4c6f0f5b",
"name": "Monkey D Garp",
"phone": "1234",
"email": "aaa#aaa.com",
"password": "$2a$10$WskmjNldC2TQ13Rl6ZLqROJwIux1KwM2tkCqfbiMSxWKRUAgsQWn.",
"role": "user"
},
{
"status": "not verified",
"_id": "5ce2409399c7952d4c6f0f5d",
"name": "Monkey D Garp",
"phone": "1234",
"email": "ccc#ccc.com",
"password": "$2a$10$186wQau8GBtqOORovWP7..r8bwSAW1kK9Cb0lT8ckeNFSkEDYjOuu",
"role": "staff"
}
]
this is my controller
exports.get_Account = async (req, res) => {
const { _id, name, email, phone, status, ac_key, ac_value } = req.query
const accounts = await Account.find({
// query database query
...(_id && {_id : { $in : _id.split(",") }}),
...(name && {$text : { $search: name }}),
...(email && {email : { $in : email.split(",") }}),
...(phone && {phone : { $in : phone.split(",") }}),
...(status && {status : { $in : status.split(",") }}),
});
const newAcc = await accounts.map(async account => {
const accMeta = await AccountMeta.find({
...({account_id : account._id}),
...(ac_key && {key : ac_key}),
...(ac_value && {value : ac_value})
});
console.log('accMeta', accMeta)
const new_account = {};
await accMeta.map(editMeta => {
new_account[editMeta.key] = editMeta.value;
});
let dynamicAccount = Object.assign({}, account._doc, new_account); //cuma
return {...dynamicAccount}
});
await Promise.all(newAcc).then(result => res.status(200).json(result))
};
thanks in advance

Join two collection in mongoDB and extract out data in node js

I am using MongoDB 3.6 for my project.
I have 2 collections "users" and "follow". I want to extract out details of user's followers and following (like an Instagram app).
users collection
{
"id" : "1",
"name" : "abc",
"age" : "26"
},
{
"id" : "2",
"name" : "xyz",
"age" : "22"
},
{
"id" : "3",
"name" : "qwe",
"age" : "23"
}
follow collection
{
"id" : "2",
"follow id" : "1"
},
{
"id" : "3",
"follow id" : "1"
},
{
"id" : "1",
"follow id" : "2"
},
{
"id" : "2",
"follow id" : "3"
},
{
"id" : "1",
"follow id" : "3"
}
Now i want following list of id 2 So id 2 is following id 1 and id 3
So, Output should be like this
{
"id" : "1",
"name" : "abc",
"age" : "26"
},
{
"id" : "3",
"name" : "qwe",
"age" : "23"
}
For that, I am using $lookup aggregation. But this is not giving the desired output which I want.
Here is my code -
Follow.aggregate([
{
$lookup:{
from:"users",
localField:"id",
foreignField:"id",
as:"fromItems"
}
},
{
$replaceRoot:{newRoot: {$mergeObjects: [ { $arrayElemAt: ["$fromItems", 0 ] }, "$$ROOT" ] } }
},
{ $project :
{
fromItems : 0
}
}
], callback)
For more understanding please refer the image
To get following list of id 2 you can use following query:
Follow.aggregate([
{
$match: { "id": "2" }
},
{
$lookup:{
from:"users",
localField:"follow id",
foreignField:"id",
as:"fromItems"
}
},
{
$replaceRoot:{newRoot: {$mergeObjects: [ { $arrayElemAt: ["$fromItems", 0 ] }, "$$ROOT" ] } }
},
{ $project :
{
id : "$follow id",
name: 1,
age: 1
}
}
])
So the point here is that you have a relation between id and follow id and after $lookup phase follow id becomes the new id since it's parent-child relation.
EDIT:
3.4 solution below
Follow.aggregate([
{
$match: { "id": "2" }
},
{
$lookup:{
from:"users",
localField:"follow id",
foreignField:"id",
as:"fromItems"
}
},
{
$project: {
id: "$follow id",
from: { $arrayElemAt: ["$fromItems", 0 ] }
}
},
{ $project :
{
id : 1,
name: "$from.name",
age: "$from.age"
}
}
])

traverse a json tree structure and add all nodes into a list

So i have a json object that i would like to traverse and add all the nodes in a linear list.below is my json
[{ "name" : "Joe", "age" : "21", "children" : [
{ "name" : "Smith", "age" : "42", "children" : [] },
{ "name" : "Gary", "age" : "21", "children" : [
{ "name" : "Jenifer", "age" : "23", "children" : [
{ "name" : "Dani", "age" : "32", "children" : [] },
{ "name" : "Max", "age" : "34", "children" : [] }
]}
]}
]},
{ "name" : "Albert", "age" : "33", "children" : [] },
{ "name" : "Ron", "age" : "29", "children" : [] }
];
and i want to create a list of all objects present in the tree, objects need to be like this: { "name" : "Joe", "age" : "21"}
Using a recursive function is an easy to traverse and flatten your array. Here's a sample algorithim:
function flatten(items, result = []) {
if (items.length) {
var item = items.shift();
result.push(item);
if (item.children && item.children.length) {
result = flatten(item.children, result);
}
return flatten(items, result);
} else {
return result;
}
}
var people = [{
"name": "Joe",
"age": "21",
"children": [{
"name": "Smith",
"age": "42",
"children": []
}, {
"name": "Gary",
"age": "21",
"children": [{
"name": "Jenifer",
"age": "23",
"children": [{
"name": "Dani",
"age": "32",
"children": []
}, {
"name": "Max",
"age": "34",
"children": []
}]
}]
}]
}, {
"name": "Albert",
"age": "33",
"children": []
}, {
"name": "Ron",
"age": "29",
"children": []
}];
console.log(flatten(people));
The easiest way to solve this would be to transverse your tree structure by using recursive function.
In my solution I make use of the instanceOf API to check what type of element the transverse is at and then determine what actions to be taken.
See:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/instanceof
Example:
let result = [];
let people =
[
{ "name" : "Joe", "age" : "21", "children" : [
{ "name" : "Smith", "age" : "42", "children" : [] },
{ "name" : "Gary", "age" : "21", "children" : [
{ "name" : "Jenifer", "age" : "23", "children" : [
{ "name" : "Dani", "age" : "32", "children" : [] },
{ "name" : "Max", "age" : "34", "children" : [] }
]}
]}
]},
{ "name" : "Albert", "age" : "33", "children" : [] },
{ "name" : "Ron", "age" : "29", "children" : [] }
];
function transverse(element, result) {
if (element instanceof Array)
element.forEach(item => { transverse(item, result); });
else if (element instanceof Object) {
result.push({ name: element.name, age: element.age });
if (element.hasOwnProperty("children")) {
transverse(element.children, result);
}
}
}
transverse(people, result);
console.log(result);
Output:
[ { name: 'Joe', age: '21' },
{ name: 'Smith', age: '42' },
{ name: 'Gary', age: '21' },
{ name: 'Jenifer', age: '23' },
{ name: 'Dani', age: '32' },
{ name: 'Max', age: '34' },
{ name: 'Albert', age: '33' },
{ name: 'Ron', age: '29' } ]
Assuming it's a simple traversal with no sorting it can be accomplished with two simple functions:
function visitChild(node, array) {
array[array.length] = { name: node.name, age:node.age };
if (node.children && node.children.length) {
node.children.forEach( function(child) { visitChild(child, array); } );
}
}
function traverseTree(root, list = []) {
if (root.length) {
root.forEach( function(node){ visitChild(node, list); });
}
return list;
}
console.log( traverseTree(tree) );
Since this has been brought back up, we might want to visit a simpler ES6 solution:
const extract = (people = []) =>
people .flatMap (({children = [], ... rest}) => [rest, ... extract (children)])
const people = [{name: "Joe", age: "21", children: [{name: "Smith", age: "42", children: []}, {name: "Gary", age: "21", children: [{name: "Jenifer", age: "23", children: [{name: "Dani", age: "32", children: []}, {name: "Max", age: "34", children: []}]}]}]}, {name: "Albert", age: "33", children: []}, {name: "Ron", age: "29", children: []}]
console .log (extract (people))
.as-console-wrapper {max-height: 100% !important; top: 0}
We implement a very simple (preorder) depth-first traversal of the hierarchy returning everything but the "children" property at each node.

How to remove an Item from an Mongodb array documents

I have the following mongodb collection named Posts with document like following:
{
"_id" : "111",
"comments" : [
{
"replyPost" : "aaaa",
"username" : "John Doe"
},
{
"replyPost" : "bbbb",
"username" : "Jane Smith"
},
{
"replyPost" : "cccc",
"username" : "Jane Smith"
},
{
"replyPost" : "dddd",
"username" : "Jane Smith"
}
]
}
I am trying to remove an array item with the replyPost: "cccc" so the result would be:
{
"_id" : "111",
"comments" : [
{
"replyPost" : "aaaa",
"username" : "John Doe"
},
{
"replyPost" : "bbbb",
"username" : "Jane Smith"
},
{
"replyPost" : "dddd",
"username" : "Jane Smith"
}
]
}
I have tried .update method with $pull refering to mongodb document
https://docs.mongodb.com/manual/reference/operator/update/pull/
Posts.update(
{_id: this._id},
{ $pull: { comments: { replyPost:"cccc"} } }
);
which don't seem to be working. can anyone see the problem?
See if you're getting the right _id. It's in string format.
I tried the same in mongo shell. It worked for me.
Here's the log:
> db.posts.insert({
... "_id" : "111",
... "comments" : [
... {
... "replyPost" : "aaaa",
... "username" : "John Doe"
... },
... {
... "replyPost" : "bbbb",
... "username" : "Jane Smith"
... },
... {
... "replyPost" : "cccc",
... "username" : "Jane Smith"
... },
... {
... "replyPost" : "dddd",
... "username" : "Jane Smith"
... }
... ]
... })
WriteResult({ "nInserted" : 1 })
> db.posts.update({_id:'111'},{$pull:{comments:{replyPost:'cccc'}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.posts.findOne()
{
"_id" : "111",
"comments" : [
{
"replyPost" : "aaaa",
"username" : "John Doe"
},
{
"replyPost" : "bbbb",
"username" : "Jane Smith"
},
{
"replyPost" : "dddd",
"username" : "Jane Smith"
}
]
}
If you are using mongoose, you can do:
db.posts.remove({replyPost: 'cccc'}, function(err) {
})
The first parameter can be any mongoose query expression. All matches will be removed from db.
See mongoose remove
Tested Works Fine:
Posts.update((
{"_id" : "111"},
{ $pull: {comments: {"replyPost" : "cccc"}} },
{ multi: true }
)

Count number of elements with certain properties inside JSON

I have some JSON data:
{"humans": [
{ "firstName" : "Paul", "lastName" : "Taylor", "hairs": 2 },
{ "firstName" : "Sharon", "lastName" : "Mohan", "hairs": 3 },
{ "firstName" : "Mohan", "lastName" : "Harris", "hairs": 3 },
{ "firstName" : "Deborah", "lastName" : "Goldman", "hairs": 4 },
{ "firstName" : "Mark", "lastName" : "Young", "hairs": 4 },
{ "firstName" : "Tom", "lastName" : "Perez", "hairs": 4 }
//and so on...
]}
I want to be able to count all people with 2 hairs, 3 hairs etc. Right now I am using jQuery.each() plus an incrementing count-array which works fine.
But I was wondering if there is an easier way to do this.
UPDATE:
Additional code saying what I am doing right now:
var results = eval(data.humans);
var count_array = [0, 0, 0, 0, 0, 0, 0];
$(results).each(function() {
if (this.hairs == 1) {
count_array[0]++;
}
if (this.hairs == 2) {
count_array[1]++
}
if (this.hairs == 3) {
count_array[2]++
}
if (this.hairs == 4) {
count_array[3]++
}
if (this.hairs == 5) {
count_array[4]++
}
if (this.hairs == 6) {
count_array[5]++
}
if (this.hairs == 7) {
count_array[6]++
}
});
You can use the filter function to filter an array of objects :
var data = {...}
data.humans.filter(function(o) { return o.hairs == 2 }).length
//Return the number of humans who have 2 hairs
Take a look fiddle
javascript for loop is fastest:
var counter = 0;
for (var i = 0; i < data.humans.length; i++) {
if (data.humans[i].hairs === 2) {
counter++;
}
}
My solution may be what you want
var data = {
"humans": [
{ "firstName" : "Paul", "lastName" : "Taylor", "hairs": 2 },
{ "firstName" : "Sharon", "lastName" : "Mohan", "hairs": 3 },
{ "firstName" : "Mohan", "lastName" : "Harris", "hairs": 3 },
{ "firstName" : "Deborah", "lastName" : "Goldman", "hairs": 4 },
{ "firstName" : "Mark", "lastName" : "Young", "hairs": 4 },
{ "firstName" : "Tom", "lastName" : "Perez", "hairs": 4 },
{ "firstName" : "Joseph", "lastName" : "Goldman", "hairs": 5 },
{ "firstName" : "Mary", "lastName" : "White", "hairs": 5 },
{ "firstName" : "Matthew", "lastName" : "Garcia", "hairs": 5 },
{ "firstName" : "Patricia", "lastName" : "Allen", "hairs": 5 },
{ "firstName" : "Larry", "lastName" : "Robinson", "hairs": 6 },
{ "firstName" : "Manb", "lastName" : "Lopez", "hairs": 6 },
{ "firstName" : "Jose", "lastName" : "Martinez", "hairs": 6 },
{ "firstName" : "Deborah", "lastName" : "Walker", "hairs": 6 },
{ "firstName" : "Joseph", "lastName" : "Lopez", "hairs": 6 },
{ "firstName" : "Tinman", "lastName" : "Moore", "hairs": 7 },
{ "firstName" : "Jose", "lastName" : "Jackson", "hairs": 7 },
{ "firstName" : "Karen", "lastName" : "Goldman", "hairs": 7 },
{ "firstName" : "Paul", "lastName" : "Taylor", "hairs": 7 },
{ "firstName" : "Amy", "lastName" : "Gonzalez", "hairs": 7 },
{ "firstName" : "Richard", "lastName" : "Martinez", "hairs": 7 }
]
};
var counterList = [];
$.each(data.humans,function(i,item){
counterList.push(item.hairs);
});
$.extend({
distinct : function(anArray) {
var result = [];
$.each(anArray, function(i,v){
if ($.inArray(v, result) == -1) result.push(v);
});
return result;
}
});
var uniqueCounterList= $.distinct(counterList);
var html = "";
$.each(uniqueCounterList,function(j,itemUnique){
html += "<div>Hair "+itemUnique+": "+(data.humans.filter(function(o) { return o.hairs == itemUnique }).length)+"</div>";
});
$("#count").html(html);
Or http://jsfiddle.net/8g5ggfeh/
here's an example abstracting the grouping function and getting a list style result:
var data = {
"humans": [
{ "firstName" : "Paul", "lastName" : "Taylor", "hairs": 2 },
{ "firstName" : "Sharon", "lastName" : "Mohan", "hairs": 3 },
{ "firstName" : "Mohan", "lastName" : "Harris", "hairs": 3 },
{ "firstName" : "Deborah", "lastName" : "Goldman", "hairs": 4 },
{ "firstName" : "Mark", "lastName" : "Young", "hairs": 4 },
{ "firstName" : "Tom", "lastName" : "Perez", "hairs": 4 },
{ "firstName" : "Joseph", "lastName" : "Goldman", "hairs": 5 },
{ "firstName" : "Mary", "lastName" : "White", "hairs": 5 },
{ "firstName" : "Matthew", "lastName" : "Garcia", "hairs": 5 },
{ "firstName" : "Patricia", "lastName" : "Allen", "hairs": 5 },
{ "firstName" : "Larry", "lastName" : "Robinson", "hairs": 6 },
{ "firstName" : "Manb", "lastName" : "Lopez", "hairs": 6 },
{ "firstName" : "Jose", "lastName" : "Martinez", "hairs": 6 },
{ "firstName" : "Deborah", "lastName" : "Walker", "hairs": 6 },
{ "firstName" : "Joseph", "lastName" : "Lopez", "hairs": 6 },
{ "firstName" : "Tinman", "lastName" : "Moore", "hairs": 7 },
{ "firstName" : "Jose", "lastName" : "Jackson", "hairs": 7 },
{ "firstName" : "Karen", "lastName" : "Goldman", "hairs": 7 },
{ "firstName" : "Paul", "lastName" : "Taylor", "hairs": 7 },
{ "firstName" : "Amy", "lastName" : "Gonzalez", "hairs": 7 },
{ "firstName" : "Richard", "lastName" : "Martinez", "hairs": 7 }
]
};
function groupByHair(array, groupOf) {
var groups = {};
array.forEach(function(element) {
var groupName = groupOf(element);
if (groupName in groups)
groups[groupName].push(element);
else
groups[groupName] = [element];
});
return groups;
}
var byHairs = groupByHair(data.humans , function(h) {
return h.hairs;
});
for (var hairs in byHairs) {
var hairsN = byHairs[hairs].length;
console.log('in '+ hairs +'hairs-group you have: ' +hairsN+' people');
}
fiddle
Can you try this ? It will group your data and you will get count for same.
var groupedData = _.groupBy(YourJsonName, function(d){return d.hairs});

Categories

Resources