How to change the keys in nested array of objects - javascript

Following is my array, and I need to replace the keys name with title and Email with subtitle.
I tried some ways, but I still need to fulfill my requirement. Please provide any solution to this.
const newUpdatedList = [];
resArr.forEach((res) => {
const obj = {
title: res.name,
subtitle: res.attributes.Email
};
if (res.children) {
const newList = res.children.map((ch) => {
return {
title: ch.name,
subtitle: ch.attributes.Email,
};
});
obj.children = newList;
}
newUpdatedList.push(obj);
});
const resArr =
[ { user_id : 'f7ba4795-d279-4c38-9a84-7a49522c50a2'
, name : 'Harsha ABC'
, custom_id : 'mani78989-1gfqv04bo'
, attributes : { Email: 'harsha#gmail.com', Role: 'admin'}
, children:
[ { user_id : 'd748037a-b445-41c2-b82f-4d6ee9396714'
, name : 'Lavaraju Allu'
, custom_id : 'mani78989-1gfqv472q'
, attributes : { Email: 'raju#gmail.com', Role: 'Manager'}
, children:
[ { user_id : '881c7731-b853-4ebc-b271-8f9e9215f7a1'
, name : 'Ramesh Allu'
, custom_id : 'mani78989-1gh14i13t'
, attributes : { Email: 'ramesh#gmail.com', Role: 'Retailer'}
, children:
[ { user_id : 'f7ba4795-d279-4c38-9a84-7a49522c50a2'
, name : 'Harsha ABC'
, custom_id : 'mani78989-1gh15nrev'
, attributes : { Email: 'harsha#gmail.com', Role: 'Delivery Manager'}
, children : []
} ] } ] }
, { user_id : '550cc296-d7e4-44fb-9d62-4c6755b3f6f2'
, name : 'Suresh Kunisetti'
, custom_id : 'mani78989-1gfqv6idi'
, attributes : { Email: 'suresh#gmail.com', Role: 'Super Admin'}
, children:
[ { user_id : '45cf19f8-36c1-4669-9333-1226c4f7b66b'
, name : 'Harish Three'
, custom_id : 'mani78989-1ggv5vffb'
, attributes : { Email: 'harish234#gmail.com', Role: 'Delivery Manager'}
, children : []
} ] }
, { user_id : '2c8535be-5fe7-40f0-892f-0f9bcffe0baa'
, name : 'Sandeep Bbb'
, custom_id : 'mani78989-1gh14m5p4'
, attributes : { Email: 'sandeep#gmail.com', Role: 'Delivery Manager'}
, children : []
}
, { user_id : '881c7731-b853-4ebc-b271-8f9e9215f7a1'
, name : 'Ramesh Allu'
, custom_id : 'mani78989-1gh14pc6p'
, attributes : { Email: 'ramesh#gmail.com', Role: 'Manager'}
, children : [ ]
} ] }
]
Expected output is
const resArr =
[ { user_id : 'f7ba4795-d279-4c38-9a84-7a49522c50a2'
, title : 'Harsha ABC'
, custom_id : 'mani78989-1gfqv04bo'
, attributes : { subtitle: 'harsha#gmail.com', Role: 'admin'}
, children:
[ { user_id : 'd748037a-b445-41c2-b82f-4d6ee9396714'
, title : 'Lavaraju Allu'
, custom_id : 'mani78989-1gfqv472q'
, attributes : { subtitle: 'raju#gmail.com', Role: 'Manager'}
, children:
[ { user_id : '881c7731-b853-4ebc-b271-8f9e9215f7a1'
, title : 'Ramesh Allu'
, custom_id : 'mani78989-1gh14i13t'
, attributes : { subtitle: 'ramesh#gmail.com', Role: 'Retailer'}
, children:
[ { user_id : 'f7ba4795-d279-4c38-9a84-7a49522c50a2'
, title : 'Harsha ABC'
, custom_id : 'mani78989-1gh15nrev'
, attributes : { subtitle: 'harsha#gmail.com', Role: 'Delivery Manager'}
, children : []
} ] } ] }
, { user_id : '550cc296-d7e4-44fb-9d62-4c6755b3f6f2'
, title : 'Suresh Kunisetti'
, custom_id : 'mani78989-1gfqv6idi'
, attributes : { subtitle: 'suresh#gmail.com', Role: 'Super Admin'}
, children:
[ { user_id : '45cf19f8-36c1-4669-9333-1226c4f7b66b'
, title : 'Harish Three'
, custom_id : 'mani78989-1ggv5vffb'
, attributes : { subtitle: 'harish234#gmail.com', Role: 'Delivery Manager'}
, children : []
} ] }
, { user_id : '2c8535be-5fe7-40f0-892f-0f9bcffe0baa'
, title : 'Sandeep Bbb'
, custom_id : 'mani78989-1gh14m5p4'
, attributes : { subtitle: 'sandeep#gmail.com', Role: 'Delivery Manager'}
, children : []
}
, { user_id : '881c7731-b853-4ebc-b271-8f9e9215f7a1'
, title : 'Ramesh Allu'
, custom_id : 'mani78989-1gh14pc6p'
, attributes : { subtitle: 'ramesh#gmail.com', Role: 'Manager'}
, children : []
} ] }
]

You can use the recursive function that I created. This function is taking in an object that looks like sample_obj and then recreates the resArr where name is title and email is subtitle. Take a look:
function recursive_fix(obj) {
const sample_obj = {
user_id: obj.user_id,
title: obj.name,
custom_id: obj.custom_id,
attributes: {subtitle: obj.attributes.Email, Role: obj.attributes.Role},
children: []
};
// only adding recursive if the children array is not empty
if (obj.children.length !== 0) {
obj.children.forEach((childz) => {
sample_obj.children.push({children: [recursive_fix(childz)]})
})
}
return sample_obj
};
const newUpdatedList = [];
resArr.forEach((res) => {
newUpdatedList.push(recursive_fix(res))
})

Here's a recursive solution.
const resArr= [{"user_id": "f7ba4795-d279-4c38-9a84-7a49522c50a2","name": "Harsha ABC","custom_id": "mani78989-1gfqv04bo","attributes": {"Email": "harsha#gmail.com","Role": "admin"},"children": [{"user_id": "d748037a-b445-41c2-b82f-4d6ee9396714","name": "Lavaraju Allu","custom_id": "mani78989-1gfqv472q","attributes": {"Email": "raju#gmail.com","Role": "Manager"},"children": [{"user_id": "881c7731-b853-4ebc-b271-8f9e9215f7a1","name": "Ramesh Allu","custom_id": "mani78989-1gh14i13t","attributes": {"Email": "ramesh#gmail.com","Role": "Retailer"},"children": [{"user_id": "f7ba4795-d279-4c38-9a84-7a49522c50a2","name": "Harsha ABC","custom_id": "mani78989-1gh15nrev","attributes": {"Email": "harsha#gmail.com","Role": "Delivery Manager"},"children": []}]}]},{"user_id": "550cc296-d7e4-44fb-9d62-4c6755b3f6f2","name": "Suresh Kunisetti","custom_id": "mani78989-1gfqv6idi","attributes": {"Email": "suresh#gmail.com","Role": "Super Admin"},"children": [{"user_id": "45cf19f8-36c1-4669-9333-1226c4f7b66b","name": "Harish Three","custom_id": "mani78989-1ggv5vffb","attributes": {"Email": "harish234#gmail.com","Role": "Delivery Manager"},"children": []}]},{"user_id": "2c8535be-5fe7-40f0-892f-0f9bcffe0baa","name": "Sandeep Bbb","custom_id": "mani78989-1gh14m5p4","attributes": {"Email": "sandeep#gmail.com","Role": "Delivery Manager"},"children": []},{"user_id": "881c7731-b853-4ebc-b271-8f9e9215f7a1","name": "Ramesh Allu","custom_id": "mani78989-1gh14pc6p","attributes": {"Email": "ramesh#gmail.com","Role": "Manager"},"children": []}]}]
function changeTitles(Obj){
Obj.title = Obj.name;
Obj.attributes.subtitle = Obj.attributes.Email;
delete Obj.name;
delete Obj.attributes.Email;
if (Obj.children) {
Obj.children.forEach(changeTitles)
}
}
const clone = JSON.parse(JSON.stringify(resArr)) // Because the function mutates the object
clone.forEach(changeTitles)
console.log(clone)

I was a little late with my answer, so it looks like a copy of Brother58697's answer. The only difference is maybe the structuredClone() method, a newish global method:
const resArr= [ { "user_id": "f7ba4795-d279-4c38-9a84-7a49522c50a2", "name": "Harsha ABC", "custom_id": "mani78989-1gfqv04bo", "attributes": { "Email": "harsha#gmail.com", "Role": "admin" }, "children": [ { "user_id": "d748037a-b445-41c2-b82f-4d6ee9396714", "name": "Lavaraju Allu", "custom_id": "mani78989-1gfqv472q", "attributes": { "Email": "raju#gmail.com", "Role": "Manager" }, "children": [ { "user_id": "881c7731-b853-4ebc-b271-8f9e9215f7a1", "name": "Ramesh Allu", "custom_id": "mani78989-1gh14i13t", "attributes": { "Email": "ramesh#gmail.com", "Role": "Retailer" }, "children": [ { "user_id": "f7ba4795-d279-4c38-9a84-7a49522c50a2", "name": "Harsha ABC", "custom_id": "mani78989-1gh15nrev", "attributes": { "Email": "harsha#gmail.com", "Role": "Delivery Manager" }, "children": [] } ] } ] }, { "user_id": "550cc296-d7e4-44fb-9d62-4c6755b3f6f2", "name": "Suresh Kunisetti", "custom_id": "mani78989-1gfqv6idi", "attributes": { "Email": "suresh#gmail.com", "Role": "Super Admin" }, "children": [ { "user_id": "45cf19f8-36c1-4669-9333-1226c4f7b66b", "name": "Harish Three", "custom_id": "mani78989-1ggv5vffb", "attributes": { "Email": "harish234#gmail.com", "Role": "Delivery Manager" }, "children": [] } ] }, { "user_id": "2c8535be-5fe7-40f0-892f-0f9bcffe0baa", "name": "Sandeep Bbb", "custom_id": "mani78989-1gh14m5p4", "attributes": { "Email": "sandeep#gmail.com", "Role": "Delivery Manager" }, "children": [] }, { "user_id": "881c7731-b853-4ebc-b271-8f9e9215f7a1", "name": "Ramesh Allu", "custom_id": "mani78989-1gh14pc6p", "attributes": { "Email": "ramesh#gmail.com", "Role": "Manager" }, "children": [] } ] } ];
function trans(arr){
arr.forEach((o)=>{
o.title=o.name; delete(o.name);
o.attributes.subtitle=o.attributes.Email; delete(o.attributes.Email);
trans(o.children)
})
}
let result=structuredClone(resArr);
trans(result);
console.log(result);

I am not 100% sure I understand correctly what you're trying to do, but it seems you are trying to change the key names in an array of objects. Let me know if this is wrong. Something like this would work in that case"
const arrayOfObj = [{
name: 'value1',
email: 'value2'
}, {
name: 'value1',
email: 'value2'
}];
const newArrayOfObj = arrayOfObj.map(({
name: title,
email: subtitle,
...rest
}) => ({
title,
subtitle,
...rest
}));
console.log(newArrayOfObj);
found this answer here

A quick solution could be to stringify, string replace and parse back to object/array.
Something like this:
const asString = JSON.stringify(resArr);
const replacedNames = asString.replace(/name/g, "title");
const replacedEmail = replacedNames.replace(/Email/g, "subtitle");
const result = JSON.parse(replacedEmail);
the changed object/array is in result.

One of the Simplest way we can use is to use Object.assign something like this:
a={'name': 'xyz', 'Email': 'xyz#gmail.com'};
b= Object.assign({'title': a.name, 'subtitle': a.Email});

Related

how to avoid duplicate key error collection in mongodb

i want to build a cart for my website, this is the schema for the cart:
const productSchema = require("./product")[1];
const cartItemSchema = new Schema<CartItem>(
{
product: productSchema,
quantity: {
type: Number,
required: true,
min: [1, "Quantity can not be less then 1."],
},
},
{
timestamps: true,
}
);
const CartSchema = new Schema(
{
userID: {
type: Schema.Types.ObjectId,
ref: "User",
},
items: [cartItemSchema],
},
{ timestamps: true }
);
module.exports = model<Cart>("Cart", CartSchema);
the problem is, when I add a product in a specific user cart, while the same product is allready added to another user cart document, I get this error:
"message":"cannot add to cart E11000 duplicate key error collection: elec-store.carts index: items.productID_1 dup key: { items.productID: null }, stack: MongoError: E11000 duplicate key error collection: elec-store.carts index: items.productID_1 dup key
this is the add function
public async add(cartItem: CartItem, userID: string): Promise<Cart> {
let cartInDB = null;
await CartModel.findOne({ userID: userID }, (err, cart) => {
cartInDB = cart;
});
if (AppUtils.hasValue(cartInDB)) {
const index = cartInDB.items.findIndex(
(item) => item.product._id.toString() === cartItem.product._id
);
if (index !== -1) {
cartInDB.items[index].quantity =
cartInDB.items[index].quantity + cartItem.quantity;
cartInDB.items[index].product._id = cartItem.product._id;
const cartAfterAdding = await cartInDB.save();
return cartAfterAdding;
} else {
await CartModel.update(
{ _id: cartInDB._id },
{ $push: { items: cartItem } }
);
}
return cartInDB;
} else {
const itemsArray: CartItem[] = [];
itemsArray.push(cartItem);
let createdCart = new CartModel({
userID: userID,
items: itemsArray,
});
await createdCart.save(); \\ this is where the problem occurs
return createdCart;
}
}
and this is how my cart looks like in mongodb document:
db.carts.find().pretty()
{
"_id" : ObjectId("60ea9fb81b2b4c048c3b1544"),
"userID" : ObjectId("60dee5e1da81bd274cd304de"),
"items" : [
{
"_id" : ObjectId("60ea9fb81b2b4c048c3b1545"),
"product" : {
"_id" : ObjectId("60e62cb21f74572b7c0b3a30"),
"name" : "tv",
"description" : "the best tv",
"categoryID" : 2,
"quantity" : "2",
"serialNumber" : "226swaq12",
"price" : 2000,
"imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
},
"quantity" : 6,
"createdAt" : ISODate("2021-07-11T07:37:29.790Z"),
"updatedAt" : ISODate("2021-07-11T07:38:15.583Z")
},
{
"_id" : ObjectId("60eaa16b1b2b4c048c3b155d"),
"product" : {
"_id" : ObjectId("60e066009be1060748201ad3"),
"name" : "samsung tv",
"description" : "the best tv",
"quantity" : "2",
"categoryID" : 2,
"serialNumber" : "2212",
"price" : 2000,
"imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
},
"quantity" : 9,
"updatedAt" : ISODate("2021-07-11T07:46:19.313Z"),
"createdAt" : ISODate("2021-07-11T07:44:43.764Z")
}
],
"createdAt" : ISODate("2021-07-11T07:37:29.792Z"),
"updatedAt" : ISODate("2021-07-11T07:46:19.314Z"),
"__v" : 0
}
I use mongoose.Schema to create new schemas and then when making reference to a different schema I do it like this:
product: { type: mongoose.Schema.Types.ObjectId, ref: 'product' },
If later you need to show also the product info (db.carts.find()), you can use populate() to replace the reference for all the product entries.
You can use upsert true.
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
}
)
For example -
db.books.update(
{ item: "ZZZ135" }, // Query parameter
{ // Replacement document
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
},
{ upsert: true } // Options
)
This may help: Mongo Update

Push an object to an array which is a field of an object in a array Mongoose

Basically I have the following schema.
{
...,
description: {
type: String,
required: true,
trim: true
},
tags: {
type: [{
type: String
}]
},
lessons: [{
name: String,
description: String,
video_path: String,
comments: [
{
user: mongoose.Schema.ObjectId,
content: String,
createdAt: {
type: Date,
default: Date.now
}
}
]
}]
,
createdAt: {
type: Date
}
}
I want to insert the following object to the comments array of a lesson object when the id of the lesson object is given.
{
userId: "5e1b4790f7a3ca42accfeed3",
content: "First comment"
}
The following is what I have tried. However it doesn't throw any error, but it's not inserting any comments to the DB also. Thanks for any helpful advice.
addComment: async (courseId, lessonId, userId, content, callback) => {
Course.update(
{ _id: courseId, "lessons._id": lessonId },
{
$push: {
comments: {
user: userId,
content: content
}
}
},
function(err, data) {
if (err) {
console.log(err);
return callback(err, null);
} else {
console.log(data);
return callback(null, data);
}
}
);
}
EDIT:
Collection data:
{
"_id" : ObjectId("5e1b4790f7a3ca42accfeed3"),
"tags" : [ "mathematics", "beginner", "fundamentals" ],
"name" : "Mathematics Toobox",
"description" : "Mathematics includes the study of such topics as quantity (number theory), structure (algebra), space (geometry), and change (mathematical analysis).",
"price" : 1500,
"lessons" : [
{
"_id" : ObjectId("5e1b48d9f7a3ca42accfeed4"),
"name" : "Welcome to the course",
"description" : "Welcome to Mathematics Toolbox course\n I’ll be your instructor for this course that runs for xx weeks ending on XXXXX.\n1. Access the technology tutorial located on your My Home page if you are new to the learning Hub, this online learning management system.",
"video_path" : "uploads\\1578846427336-Shakira - Hips Don't Lie ft. Wyclef Jean.mp4"
},
{
"_id" : ObjectId("5e1e8f80cf166a2cb82b7a5e"),
"name" : "Number system",
"description" : "Baby just love me love me love me\nBaby just hold me hold me hold me\nOh love me ",
"video_path" : "uploads\\1579061121969-Ellis - Migraine (feat. Anna Yvette) [NCS Release].mp4"
}
],
"createdAt" : ISODate("2020-01-12T16:21:36.778Z"),
"__v" : 0,
"cover_path" : "uploads\\1578846099107-img_4.jpg"
}
There are a few problems in your schema.
I think you want to have an array of string tags.
Also you need to use ref property to make a reference to the User model.
So schema must be updated like this:
(I assume that you used User in model creation.)
const mongoose = require("mongoose");
const courseSchema = new mongoose.Schema({
description: {
type: String,
required: true,
trim: true
},
tags: {
type: [String]
},
lessons: [
{
name: String,
description: String,
video_path: String,
comments: [
{
user: {
type: mongoose.Schema.ObjectId,
ref: "User"
},
content: String,
createdAt: {
type: Date,
default: Date.now
}
}
]
}
],
createdAt: {
type: Date
}
});
module.exports = mongoose.model("Course", courseSchema);
Now you can use findByIdAndUpdate method with push and filtered positional operator $.
to add a comment like this:
Course.findByIdAndUpdate(
{ _id: courseId },
{
$push: { "lessons.$[lesson].comments": { user: userId, content } }
},
{
arrayFilters: [{ "lesson._id": lessonId }],
new: true
},
function(err, data) {
if (err) {
console.log(err);
return callback(err, null);
} else {
console.log(data);
return callback(null, data);
}
}
);
Test:
Let's say you have an user with _id: 5e20954dc6e29d1b182761c9, and a course like this:
{
"tags": [
"tag1",
"tag2"
],
"_id": "5e209631a90e651e9c238df2",
"description": "description1",
"lessons": [
{
"comments": [],
"_id": "5e209631a90e651e9c238df3",
"name": "lesson1 name",
"description": "lesson1 description",
"video_path": "lesson1 video_path"
}
],
}
When you send a comment with these values:
courseId = "5e209631a90e651e9c238df2",
lessonId = "5e209631a90e651e9c238df3",
userId = "5e20954dc6e29d1b182761c9",
content = "Comment Content"
The result will be:
{
"_id" : ObjectId("5e209631a90e651e9c238df2"),
"tags" : [
"tag1",
"tag2"
],
"description" : "description1",
"lessons" : [
{
"comments" : [
{
"_id" : ObjectId("5e2099799edf132a08c2b997"),
"user" : ObjectId("5e20954dc6e29d1b182761c9"),
"content" : "Comment Content",
"createdAt" : ISODate("2020-01-16T20:12:25.243+03:00")
}
],
"_id" : ObjectId("5e209631a90e651e9c238df3"),
"name" : "lesson1 name",
"description" : "lesson1 description",
"video_path" : "lesson1 video_path"
}
]
}
This is what finally worked for me.
const newData = {
'lessons.$.comments': {
user: userId,
content: content
}
}
Course.updateOne({_id: courseId,'lessons._id': lessonId}, {'$push':
newData
}, function(err,num) {
console.log(num)
if(num.nModified > 0){
callback(null,num)
}
else if(err){
callback(err,null)
}
})
}

Group collection based on the common values of a field mongodb

My collection looks like this
{
"email" : "tp#sd.com",
"subscriptions" : [
{
"default" : false,
"interval" : "weekly",
"tags" : [
{
"name" : "group-1",
"value" : "g1-value-1"
},
{
"name" : "group-1",
"value" : "g1-value-2"
},
{
"name" : "group-2",
"value" : "g2-value-1"
},
{
"name" : "group-3",
"value" : "g3-value-1"
},
{
"name" : "group-3",
"value" : "g3-value-2"
}
]
},
{
"email":"lol#xyz.com",
"subscriptions" : [
{
"default" : false,
"interval" : "weekly",
"tags" : [
{
"name" : "group-1",
"value" : "g1-value-2"
},
{
"name" : "group-1",
"value" : "g1-value-1"
},
{
"name" : "group-2",
"value" : "g2-value-1"
},
{
"name" : "group-2",
"value" : "g2-value-3"
},
{
"name" : "group-3",
"value" : "g3-value-1"
}
]
}
}
I want to group this to an array of objects which contain emails and common group values.
for example, A user-1 has g1-value-1 and user-2 also has g1-value-1, maybe along with other values as well. But these users should be grouped together along with their tags. How do I achieve this?
Surprisingly it's quite an easy query:
db.collection.aggregate([
{
$unwind: "$subscriptions"
},
{
$unwind: "$subscriptions.tags"
},
{
$group: {
_id: "$subscriptions.tags.value",
emails: {$addToSet: "$email"}
}
}
]);
The result will look like this:
[
{
_id: "g1-value-1",
emails: [
"tp#sd.com",
"lol#xyz.com"
]
},
{
_id: "g1-value-2",
emails: [
"tp#sd.com",
"lol#xyz.com"
]
},
{
_id: "g2-value-1",
emails: [
"tp#sd.com",
"lol#xyz.com"
]
},
{
_id: "g2-value-3",
emails: [
"lol#xyz.com"
]
},
{
_id: "g3-value-1",
emails: [
"tp#sd.com",
"lol#xyz.com"
]
},
{
_id: "g3-value-2",
emails: [
"tp#sd.com",
]
},
]

return last occurrence of name (many names) in an array of objects

Given the following data source:
[
{
"Username" : "Patrick",
"Time" : "08:01:32",
"Status" : "log in"
},
{
"Username" : "Patrick",
"Time" : "08:34:31",
"Status" : "idle"
},
{
"Username" : "Patrick",
"Time" : "08:52:10",
"Status" : "meeting"
},
{
"Username" : "Patrick",
"Time" : "10:07:52",
"Status" : "daily tasks"
},
{
"Username" : "Patrick",
"Time" : "12:00:11",
"Status" : "lunch"
},
{
"Username" : "Mark",
"Time" : "07:40:32",
"Status" : "log in"
},
{
"Username" : "Mark",
"Time" : "08:54:31",
"Status" : "meeting"
},
{
"Username" : "Mark",
"Time" : "09:52:10",
"Status" : "idle"
},
{
"Username" : "Mark",
"Time" : "10:07:52",
"Status" : "daily tasks"
},
{
"Username" : "Mark",
"Time" : "12:30:11",
"Status" : "lunch"
}
]
How do I get the last occurrence of each name in this array in a simple way? I was thinking about the filter function however I'm not sure how to proceed on this. Any support or tip will be highly appreciated.
The expected outcome should be as follows:
[
{
"Username" : "Patrick",
"Time" : "12:00:11",
"Status" : "lunch"
},
{
"Username" : "Mark",
"Time" : "12:30:11",
"Status" : "lunch"
}
]
Using ES6, you can reduce the array into a map, and then spread the values back to an array:
const data = [{"Username":"Patrick","Time":"08:01:32","Status":"log in"},{"Username":"Patrick","Time":"08:34:31","Status":"idle"},{"Username":"Patrick","Time":"08:52:10","Status":"meeting"},{"Username":"Patrick","Time":"10:07:52","Status":"daily tasks"},{"Username":"Patrick","Time":"12:00:11","Status":"lunch"},{"Username":"Mark","Time":"07:40:32","Status":"log in"},{"Username":"Mark","Time":"08:54:31","Status":"meeting"},{"Username":"Mark","Time":"09:52:10","Status":"idle"},{"Username":"Mark","Time":"10:07:52","Status":"daily tasks"},{"Username":"Mark","Time":"12:30:11","Status":"lunch"}];
const result = [...data.reduce((m, o) => m.set(o.Username, o), new Map()).values()];
console.log(result);
In ES5 you can reduce the array to an object that will contain the unique items, and then map the object back to an array using Object#keys:
var data = [{"Username":"Patrick","Time":"08:01:32","Status":"log in"},{"Username":"Patrick","Time":"08:34:31","Status":"idle"},{"Username":"Patrick","Time":"08:52:10","Status":"meeting"},{"Username":"Patrick","Time":"10:07:52","Status":"daily tasks"},{"Username":"Patrick","Time":"12:00:11","Status":"lunch"},{"Username":"Mark","Time":"07:40:32","Status":"log in"},{"Username":"Mark","Time":"08:54:31","Status":"meeting"},{"Username":"Mark","Time":"09:52:10","Status":"idle"},{"Username":"Mark","Time":"10:07:52","Status":"daily tasks"},{"Username":"Mark","Time":"12:30:11","Status":"lunch"}];
var uniques = data.reduce(function(m, o) {
m[o.Username] = o;
return m;
}, Object.create(null));
var result = Object.keys(uniques).map(function(key) {
return uniques[key];
});
console.log(result);
You could use a hash table and use an explicit check if the time is greater than the last time of the inserted object.
This proposal works with unsorted data as well.
var data = [{ Username: "Patrick", Time: "08:01:32", Status: "log in" }, { Username: "Patrick", Time: "08:34:31", Status: "idle" }, { Username: "Patrick", Time: "08:52:10", Status: "meeting" }, { Username: "Patrick", Time: "10:07:52", Status: "daily tasks" }, { Username: "Patrick", Time: "12:00:11", Status: "lunch" }, { Username: "Mark", Time: "07:40:32", Status: "log in" }, { Username: "Mark", Time: "08:54:31", Status: "meeting" }, { Username: "Mark", Time: "09:52:10", Status: "idle" }, { Username: "Mark", Time: "10:07:52", Status: "daily tasks" }, { Username: "Mark", Time: "12:30:11", Status: "lunch" }],
hash = Object.create(null),
result = data.reduce(function (r, o) {
if (!(o.Username in hash)) {
hash[o.Username] = r.push(o) - 1;
return r;
}
if (r[hash[o.Username]].Time < o.Time) {
r[hash[o.Username]] = o;
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use .filter() with .some() within callback to check if any elements of array at greater indexes than current index within .filter() has current property value
const arr = [{"Username":"Patrick","Time":"08:01:32","Status":"log in"}
,{"Username":"Patrick","Time":"08:34:31","Status":"idle"}
,{"Username":"Patrick","Time":"08:52:10","Status":"meeting"}
,{"Username":"Patrick","Time":"10:07:52","Status":"daily tasks"}
,{"Username":"Patrick","Time":"12:00:11","Status":"lunch"}
,{"Username":"Mark","Time":"07:40:32","Status":"log in"}
,{"Username":"Mark","Time":"08:54:31","Status":"meeting"}
,{"Username":"Mark","Time":"09:52:10","Status":"idle"}
,{"Username":"Mark","Time":"10:07:52","Status":"daily tasks"}
,{"Username":"Mark","Time":"12:30:11","Status":"lunch"}];
let res = arr.filter(({Username:a}, i) =>
!arr.some(({Username:b}, k) => k > i && a == b));
console.log(res);
In case someone is interested in getting the first ocurrence of each username there is a simple way to do it tweaking Nina's code a bit as follows:
var data = [{ Username: "Patrick", Time: "08:01:32", Status: "log in" }, { Username: "Patrick", Time: "08:34:31", Status: "idle" }, { Username: "Patrick", Time: "08:52:10", Status: "meeting" }, { Username: "Patrick", Time: "10:07:52", Status: "daily tasks" }, { Username: "Patrick", Time: "12:00:11", Status: "lunch" }, { Username: "Mark", Time: "07:40:32", Status: "log in" }, { Username: "Mark", Time: "08:54:31", Status: "meeting" }, { Username: "Mark", Time: "09:52:10", Status: "idle" }, { Username: "Mark", Time: "10:07:52", Status: "daily tasks" }, { Username: "Mark", Time: "12:30:11", Status: "lunch" }],
hash = Object.create(null),
result = data.reduce(function (r, o) {
if (!(o.Username in hash)) {
hash[o.Username] = r.push(o) - 1;
return r;
}
if (r[hash[o.Username]].Time > o.Time) {
r[hash[o.Username]] = o;
}
return r;
}, []);
console.log(result);
Only change the if statement (if (r[hash[o.Username]].Time > o.Time)) and this will get you the results you need. I hope this helps someone out there.

mongoDB: Update nested array object

I would like the nested object with the id BAHx9KeKjuMePce6f to be updated:
{
"_id" : "sgG6G9XTvvjj7uxwQ",
"target" : [
{
"title" : "content",
"id" : "ePce6fBAHx9KeKjuM"
},
{
"title" : "content",
"id" : "BAHx9KeKjuMePce6f" <--
}
]
}
So this is what I tried:
var newData = { title: "new", one: "more", id: 'BAHx9KeKjuMePce6f' };
Collection.update(
{ _id: 'sgG6G9XTvvjj7uxwQ', 'target.id': 'BAHx9KeKjuMePce6f' },
{ $set: newData }
);
The result should be:
{
"_id" : "sgG6G9XTvvjj7uxwQ",
"target" : [
{
"title" : "content",
"id" : "ePce6fBAHx9KeKjuM"
},
{
"title": "new",
"one": "more",
"id" : "BAHx9KeKjuMePce6f"
}
]
}
In order to update specific element in array you can use mongodb positional $ operator.
Try the following query:
var newData = { title: "new", one: "more", id: 'BAHx9KeKjuMePce6f' };
Collection.update(
{ _id: 'sgG6G9XTvvjj7uxwQ', 'target.id': 'BAHx9KeKjuMePce6f' },
{ $set: { 'target.$': newData } }
);
You need the use the positional parameter $ to indicate you want to update the array element, rather than the root of the document, see the documentation:
Collection.update({
_id: 'sgG6G9XTvvjj7uxwQ',
'target.id': 'BAHx9KeKjuMePce6f'
}, {
$set: {
"target.$": newData
}
});

Categories