I Have an object inside another object and I want to spread the inner one, my reason is when I want to call the object by it's id
My object
Resolver [
{ _id: { _id: '123456789', totaloutcome: 'DONE' }, count: 4 },
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_APPROVED_ONLINE' },
count: 33
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_CANCELLED' },
count: 1
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_UNKNOWN' },
count: 1
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_DECLINED' },
count: 15
}
]
As shown above I want to append 'count' attribut inside '_id' attribute , i couldn't spread the inner one so How can I do it
You can do this using the spread operator:
array.map((item) => {
return { ...item, ...item._id };
});
How to spread object inside object
We are useing ... for spreding object into inner obj.
const user = {
name:"siva",
age: 25
}
//spred user in to below obj
const userInfo = {
_id:"123445",
phno: 77777777777
...user
}```
Code
const Resolver= [
{ _id: { _id: '123456789', totaloutcome: 'DONE' }, count: 4 },
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_APPROVED_ONLINE' },
count: 33
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_CANCELLED' },
count: 1
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_UNKNOWN' },
count: 1
},
{
_id: { _id: '05000002', totaloutcome: 'OUTCOME_DECLINED' },
count: 15
}
]
const result = Resolver.map(({_id, ...rest}) => {
return { ..._id, ...rest };
});
console.log(result)
Related
I have data like this
finalValue [
{ _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }
]
I want to spread the inner object and change the keys to name and value to make final value looks like this
finalValue [
{ name: 'OUTCOME_APPROUVED' , value: 1 },
{ name: 'OUTCOME_SWITCH_INTERFACE' , value: 5 }
]
try this :
var finalValue = [
{ _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }
]
var newValue = finalValue.map(({_id:{_id},count}) => {
return {name:_id , value:count}
})
console.log(newValue)
[JS]
You could use map instead of spreading, and not sure about how you could spread it to format it the way you want.
const inputValue = [ { _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }]
const computedValue = inputValue.map((data) => {
return { name: data._id._id, value: data.count };
});
I have this document of timestamps sorted by time:
{
_id: '1',
timestamps: [
{
id: '589b32cf-28b3-4a25-8fd1-5e4f86682199',
time: '2022-04-13T19:00:00.122Z'
},
{
id: '781a47de-d21a-4c2c-9814-b46f4a3cfa30',
time: '2022-04-13T20:00:00.498Z'
}
]
};
I want to update a timestamp by id, change the time, and sort
example: update timestamp with id: '589b32cf-28b3-4a25-8fd1-5e4f86682199':
{
id: '589b32cf-28b3-4a25-8fd1-5e4f86682199',
time: '2022-04-13T20:30:00.122Z'
}
the updated document should like this:
{
_id: '1',
timestamps: [
{
id: '32bb3-2222-1111-j878-b4000a3wwa30',
time: '2022-04-13T19:30:00.122Z'
},
{
id: '589b32cf-28b3-4a25-8fd1-5e4f86682199',
time: '2022-04-13T20:30:00.122Z'
}
]
};
I came up with this method to update and sort each element in the array:
const updateResult = await TimestampCollection.updateOne(
{ _id: '1' },
{
$push: {
timestamps: {
$each: [{ id: timestamp.id, time: timestamp.time }],
$sort: { time: 1 }
}
}
}
);
However this pushed a new object to the array with the same id and updated time:
{
_id: '1',
timestamps: [
{
id: '589b32cf-28b3-4a25-8fd1-5e4f86682199',
time: '2022-04-13T19:00:00.122Z'
},
{
id: '32bb3-2222-1111-j878-b4000a3wwa30',
time: '2022-04-13T19:30:00.122Z'
},
{
id: '589b32cf-28b3-4a25-8fd1-5e4f86682199',
time: '2022-04-13T20:30:00.122Z'
}
]
};
Any idea how to fix this?
I didn't find a way to do this in a single query. Sadly combining $set and $push in a single query leads to a conflict...
db.collection.update({
_id: "1",
"timestamps.id": timestamp.id
},
{
"$set": {
"timestamps.$.time": timestamp.time
},
});
db.collection.update({
_id: "1",
},
{
"$push": {
"timestamps": {
"$each": [],
"$sort": {
"time": 1
}
}
}
})
This solution involves two queries. One for updating the element in the array and the other for sorting the array.
I have this Event array but can't figure out how to query into the 'guests' nested array and do two things.
count the number of guests
count the number of attended guests (marked 'Y')
{ _id: new ObjectId('1'),
name: event1,
guests: [
{
phone: +12222222222,
_id: new ObjectId,
attended: 'Y'
},
{
phone: +12344466666,
_id: new ObjectId,
attended: 'Y'
},
{ phone: +11234567890,
_id: new ObjectId,
attended:
},
{
phone: +14443332222,
_id: new ObjectId,
attended: 'Y'
},
{ phone: +19090909090,
_id: new ObjectId
attended:
}
],
},
{ _id: new ObjectId('2'),
name: event2,
guests: [
{
phone: +11111111111,
_id: new ObjectId,
attended:
},
{
phone: +12222222222,
_id: new ObjectId,
attended: 'Y'
},
{
phone: +133333333333,
_id: new ObjectId,
attended: 'Y'
}
],
},
My code below is on its 20th iteration without getting any closer.
const event = await Event.findById(req.params.id);
For MongoDB query, you can use $size for calculating the size of the array field and $filter to filter specific document(s) that matched the criteria in the projection.
db.collection.find({
_id: "1"
},
{
_id: 1,
name: 1,
guests: 1,
totalGuests: {
$size: "$guests"
},
attendedGuests: {
$size: {
"$filter": {
input: "$guests",
cond: {
$eq: [
"$$this.attended",
"Y"
]
}
}
}
}
})
Sample Mongo Playground
Yong Shun helped above but didn't get 100% of the way -- here is the full answer in case anyone encounters something like this in the future:
module.exports.showEvent = async (req, res) => {
const event = await Event.findById(req.params.id).populate('artist');
const { guest_id } = req.cookies;
let totalGuests = 0;
let attendedGuests = 0;
const eventData = await Event.aggregate([
{
"$match": {
"_id": objectId(req.params.id)
}
},
{
$project: {
_id: 1,
name: 1,
guests: 1,
totalGuests: { $cond: { if: { $isArray: "$guests" }, then: { $size: "$guests" }, else: "NA" } },
attendedGuests: {
$size: {
$filter: {
input: "$guests",
as: "guest",
cond: {
$and: [{
$eq: ["$$guest.attended", "Y"]
}]
}
}
}
}
}
}
])
if (eventData && Array.isArray(eventData) && eventData.length > 0) {
totalGuests = eventData[0].totalGuests;
attendedGuests = eventData[0].attendedGuests;
}
if (!event) {
req.flash('error', 'Cannot find that Event');
return res.redirect('/events');
}
res.render('events/show', { event, eventData });
console.log(totalGuests, attendedGuests);
};
I have this array of objects:
[
{
user: 'User_1',
date: 1603926000000,
count: 3,
},
{
user: 'User_2',
date: 1603926000000,
count: 10,
},
{
user: 'User_2',
date: 1604876400000,
count: 1,
},
]
I reduce it with this function:
const reducedDataByDate = dataByDate.reduce((acc, d) => {
const foundUser = acc.find((a) => a.user === d.user)
const value = { date: formatDate(d.date), count: d.count }
if (!foundUser) {
acc.push({ user: d.user, data: [value] })
} else {
foundUser.data.push(value)
}
return acc
}, [])
with this outcome:
[
{
user: 'User_1',
data: [
{
date: '2020-10-29',
count: 10,
},
{
date: '2020-11-09',
count: 1,
},
],
},
{
user: 'User_2',
data: [
{
date: '2020-10-29',
count: 3,
},
],
},
]
Ideally, I would like get rid of pushing values to original acc and foundUser array but have little idea how to go about that. Any input is much appreciated!
You could collect the data with a Map and get the wanted format from it.
const
data = [{ user: 'User_1', date: 1603926000000, count: 3 }, { user: 'User_2', date: 1603926000000, count: 10 }, { user: 'User_2', date: 1604876400000, count: 1 }],
result = Array.from(
data.reduce(
(m, { user, ...o }) => m.set(user, [...(m.get(user) || []), o]),
new Map
),
([user, data]) => ({ user, data })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have two arrays of objects; districts and userCounts. I am trying to reduce districts and find userCounts inside reduce
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.find(({ _id }) => _id === curr._id)
console.log(findUser)
})
all findUser is returning undefined
districts:
[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
userCounts:
[
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
well .filter() with .every() is better use case here
let districts = [
{
_id: "5efc41d74664920022b6c016",
name: "name1",
},
{
_id: "5efc41a44664920022b6c015",
name: "name2",
},
{
_id: "5efc2d84caa7964dcd843a7b",
name: "name3",
},
{
_id: "5efc41794664920022b6c014",
name: "name 4",
},
];
let userCounts = [
{ _id: "5efc2d84caa7964dcd843a7b", totalCount: 3 },
{ _id: "5efc41794664920022b6c014", totalCount: 1 },
];
const result = districts.filter((dist) => {
return userCounts.some(({ _id }) => _id === dist._id);
});
console.log(result);
const districs=[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts= [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
let filtered=userCounts.map(item=>{
return districs.find(elemnt=>elemnt._id===item._id)
})
console.log(filtered)
here you go, you can modify it however you want.
try this if you want to use reduce and modify your array:
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
const districts = [
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts = [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
console.log(result)