How to store nested Array-Object into Mongodb? - javascript

I've got struggled in storing data in MongoDB Atlas. the Array I wanted to store is like this:
Array [
Array [
"6352546fb6e1702a96df5931",
"[{\"date\":\"2022-10-21\"},{\"index\":\"6352546fb6e1702a96df5931\"},{\"setDetails\":[{\"setIndex\":0,\"result\":12,\"weight\":\"12\",\"reps\":0}]},{\"setDetails\":[{\"setIndex\":1,\"result\":25,\"weight\":\"25\",\"reps\":0}]}]",
],
Array [
"6360db542adb98c1ac717890",
null,
],
Array [
"636284882f3e1d9e6808071d",
"[]",
],
Array [
"63628afd2f3e1d9e6808071f",
null,
],
Array [
"63628b8d2f3e1d9e68080721",
null,
],
Array [
"63628bf32f3e1d9e68080723",
null,
],
Array [
"63628c092f3e1d9e68080725",
null,
],
Array [
"63628cb72f3e1d9e68080727",
null,
],
]
I tried various Schema types like array or object,
const UserWorkoutHistory = {
workout: Object, // something wrong with this line
userId: String,
};
const UserWorkoutScheme = mongoose.model(
'UserWorkoutHistory',
UserWorkoutHistory
);
module.exports = UserWorkoutScheme;
but although I got the same data on my backend correctly, nothing was stored on the DB. Could you please give a clue to find the solution?
Update:
I got data from AsyncStorage React Native:
const GetData = async () => {
try {
workoutId.map((item) => {
//console.log('item', item);
return AsyncStorage.getItem(item).then((value) => {
//setData(value);
const dataArray = JSON.parse(value);
if (dataArray.length !== 0) {
// console.log('value', data.length);
setData((data) => [...data, dataArray]);
}
});
});
} catch (e) {
alert(e.message);
}
};
then, simply send it by Axios post to the server :
const SyncData = () => {
Axios
.post('http://10.4.1.6:8080/userworkoutdata', {
data,
userId,
})
.then((res) => {
//console.log('res', res.data);
})
.catch((error) => {
console.log('error', error);
});
};
this is what I get in post route on Express js
630749ebb3c79314cc86877c //userId
[
{ date: '2022-10-21' },
{ index: '6352546fb6e1702a96df5931' },
{ setDetails: [ [Object] ] },
{ setDetails: [ [Object] ] }
] // data I wanted to store
user Id is stored correctly, but the data not

I am not sure why what you have is not working for you, I have a similar and it's working for me. But you can try
const UserWorkoutHistory = {
workout: [[mongoose.Schema.Types.Mixed]], // array of array of mixed
userId: String,
};
Or
const UserWorkoutHistory = {
workout: {type: Object},
userId: String,
};

Related

Sequelize Op.and, Op.like resulting in empty object

I'm trying to create a search endpoint with express and sequelize. When creating my 'where' object, all Op.and results in an empty object:
const where = {
[Op.and]: req.query.q.split(" ").map((q) => {
return { name: { [Op.like]: `%${q}%` } };
}),
};
console.log(where);
Resulting in the following output:
{}
Then I tried to omit the [Op.and] part and changed it to the following
const where = req.query.q.split(" ").map((q) => {
return { name: { [Op.like]: q } };
});
console.log(where);
Which outputs:
[
{
"name": {}
},
{
"name": {}
}
]
Figured it out. It's just the console.log that can't seem to handle it. My query doesn't work for some other strange but probably very logical reason.

Transform data from fetch with React

I have retrieved data from an API, and now trying to transform the data to send a POST request. I want to group two User ID's that match, and POST their common cities in a array instead of separate objects.
For example, data I retrieve looks like this:
{
"events": [
{
"city": "city-1",
"user": "d1177368-2310-11e8-9e2a-9b860a0d9039"
},
{
"city": "city-2",
"user": "d1177368-2310-11e8-9e2a-9b860a0d9039"
}
]}
I want my POST request data to look similar to this:
{
"user": {
"d1177368-2310-11e8-9e2a-9b860a0d9039": [
{
"city": [
"city-1",
"city-2"
]
}]}}
So far this is my React component for the request:
import React, { useEffect, useState } from "react";
import axios from "../data/axios";
export default function Events({ fetchEvents }) {
const [events, setEvents] = useState([]);
useEffect(() => {
async function fetchData() {
const requests = await axios.get(fetchEvents);
setEvents(requests.data.events);
return requests;
}
fetchData();
}, [fetchEvents]);
//here is my issue:
function createSessions(user, city) {
if (user === user) {
}
}
Thank you
Iterate over the events array, reducing it into an object with a user object property. The user object has the user values from the events array elements as key and the cities are pushed into a city array property.
events.reduce(
(result, el) => {
if (!result.user[el.user]) {
result.user[el.user] = [{ city: [] }];
}
result.user[el.user][0].city.push(el.city);
return result;
},
{ user: {} }
);
const data = {
events: [
{
city: "city-1",
user: "d1177368-2310-11e8-9e2a-9b860a0d9039"
},
{
city: "city-2",
user: "d1177368-2310-11e8-9e2a-9b860a0d9039"
}
]
};
const data2 = data.events.reduce(
(result, el) => {
if (!result.user[el.user]) {
result.user[el.user] = [{ city: [] }];
}
result.user[el.user][0].city.push(el.city);
return result;
},
{ user: {} }
);
console.log(data2);

Change an object value inside a loop in JavaScript

I have an array of objects like this:
const data = [{
_id:"49847444033",
name:"yoko"
},{
_id:"49847433333",
name:"doira"
}]
I have to change each item name property to something like this :
...
{
_id:"49847433333",
name:{
en:"John"
}
}
My attempt is to loop object like following :
data.forEach((item) => {
item.name = {en:"john"}
console.log(item)
})
But this always console the original item and the name property value is not modified.
const newData = data.map(user => ({ _id: user._id, name: { en: user.name } }))
I created a library to express transformations like this very simply.
const { pipe, fork, get } = require('rubico')
const data =
[ { _id: '49847444033', name: 'yoko'}
, { _id: '49847433333', name: 'doira'}
]
const onData = pipe([
fork({
_id: get('_id'), // data => data._id
name: fork({ en: get('name') }), // data => ({ en: data.name })
}),
console.log,
])
data.map(onData) /*
{ _id: '49847444033', name: { en: 'yoko' } }
{ _id: '49847433333', name: { en: 'doira' } }
*/
I've commented the code above, but to really understand rubico and get started using it, I recommend you read the intuition and then the docs
try somthing like:
const newList = data.map(obj => {
return { _id: obj._id, name: { en: obj.name } }
});
and the newList list is your new data list so you can do it:
data = newList;
EDIT:
if you have more properties you can change the return line to:
return { ...obj, name: { en: obj.name } }
what will happen here, it will deploy all the object properties as they are, and modify the name property, unfortunately, every property you want to modify, you have to re-write it.

Is their any better way to set duplicate array data instead of use data[0]

What is the best way to refactoring code and best performance Here Is what I do In getData function I query get Data from databae using async/await then I got some ugly data I try to map and delete element that duplicate data
async getData({req,res}) {
let data = await this.getData()
data = [
{
"id": 3,
"employee_id": 2290,
"getId": {
"id": 9070
},
"getName": {
"name": "test"
},
},
{
"id": 4,
"employee_id": 2291,
"getId": {
"id": 9070
},
"getName": {
"name": "test"
},
}
] //example I await call database get data look like this
//before I remove them I want to keep duplicate data I set new variable for keep them
//which part is the most ugly is their anyway to do something about this ?
const getId = data[0].getId
const getName = data[0].getName
// in this part I map and delete element that duplicate which is data.getName and data.getId
// I create seperate function for code clean
data = await this.removeElement(data)
//after that I return response data
return response.status(200).json({
status: 200,
success: true,
getId: getId,
getName: getName,
data: data
});
}
async removeElement(data) {
// im not sure is their any beeter way to do something like this ?
return Promise.all(
data.map(async item => {
await delete item.getId;
await delete item.getName;
return item;
})
);
}
so my output response will look like this :
getId : {
id : 9070
}
getName : {
name : 'test'
}
data : [
{
"id": 3,
"employee_id": 2290,
},
{
"id": 4,
"employee_id": 2291,
}
]
I really appreciate for your help thanks
Removing properties from an object is not an asynchronous process. There's no need to await it or have a Promise.all around such a loop.
To extract the two common properties from the first item of the array concisely, you can destructure:
const { getId, getName } = data[0];
Shorthand property names will help too. In full:
const data = await this.getData();
const { getId, getName } = data[0];
const trimmedData = data.map(({ id, employee_id }) => ({ id, employee_id }));
return response.status(200).json({
status: 200,
success: true,
getId,
getName,
data: trimmedData
});
The data.map(({ id, employee_id }) => ({ id, employee_id })) takes the array and constructs a new array of objects which contain only the id and employee_id properties in the original objects.
If you need to blacklist properties rather than extract the desired properties, then you can do something similar to the above with rest syntax:
const trimmedData = data.map(({ getId, getName, ...rest }) => rest);

Create map for user 'userId' as a key and all post come together in array

I know the title might sounds confusing, but I'm stuck for an hour, mainly how to put them in array. This is my mongo output-
userFavPost:
[ { post: '2920', user: '5a1d2f59cf81657f613b0683' },
{ post: '2920', user: '5a057915c31eb5601da9b75f' },
{ post: '2922', user: '5a057915c31eb5601da9b75f' },
{ post: '2998', user: '5a057915c31eb5601da9b75f' } ]
I want to create map, so that I will get data like this -
{
'5a1d2f59cf81657f613b0683' => {
post: [2920],
user: '5a1d2f59cf81657f613b0683'
},
'5a057915c31eb5601da9b75f' => {
post: [2920, 2922, 2998],
user: '5a057915c31eb5601da9b75f'
}
}
I know this is a newbie question but I'm confused!
Use array.reduce function and in the accumulator object check if there exist a key same as the user value. If it exist , then push the new value in the array , otherwise create a new key by user value and push the post value into the array
let arr = [{
post: '2920',
user: '5a1d2f59cf81657f613b0683'
},
{
post: '2920',
user: '5a057915c31eb5601da9b75f'
},
{
post: '2922',
user: '5a057915c31eb5601da9b75f'
},
{
post: '2998',
user: '5a057915c31eb5601da9b75f'
}
]
let newObj = arr.reduce(function(acc, curr) {
if (acc.hasOwnProperty(curr.user)) {
acc[curr.user].push(curr.post)
} else {
acc[curr.user] = [curr.post]
}
return acc;
}, {});
console.log(newObj)
Another take, that produces the form specified in the original post:
const userFavPost =
[ { post: '2920', user: '5a1d2f59cf81657f613b0683' },
{ post: '2920', user: '5a057915c31eb5601da9b75f' },
{ post: '2922', user: '5a057915c31eb5601da9b75f' },
{ post: '2998', user: '5a057915c31eb5601da9b75f' } ];
const postMap = userFavPost.reduce((users, entry) => ({
...users,
[entry.user]: {
...users[entry.user],
user: entry.user,
post: [
...(users[entry.user] && users[entry.user].post || []),
entry.post
]
}
}), {});
/* { '5a1d2f59cf81657f613b0683':
{ user: '5a1d2f59cf81657f613b0683', post: [ '2920' ] },
'5a057915c31eb5601da9b75f':
{ user: '5a057915c31eb5601da9b75f', post: [ '2920', '2922', '2998' ] }
} */
You could use as simple reduce with destructuring like this:
const posts= [{post:'2920',user:'5a1d2f59cf81657f613b0683'},{post:'2920',user:'5a057915c31eb5601da9b75f'},{post:'2922',user:'5a057915c31eb5601da9b75f'},{post:'2998',user:'5a057915c31eb5601da9b75f'}]
const merged = posts.reduce((acc, {user,post}) => {
// check if user already exists in the accumulator else create
acc[user] = acc[user] || {user, post:[]}
acc[user]["post"].push(post)
return acc
}, {});
console.log(merged)
You could do all that in one line like this:
const posts= [{post:'2920',user:'5a1d2f59cf81657f613b0683'},{post:'2920',user:'5a057915c31eb5601da9b75f'},{post:'2922',user:'5a057915c31eb5601da9b75f'},{post:'2998',user:'5a057915c31eb5601da9b75f'}]
const merged = posts.reduce((acc, {user,post}) =>
((acc[user] = acc[user] || {user, post:[]})["post"].push(post), acc),{});
console.log(merged)

Categories

Resources