Related
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,
};
I'm trying to do a dynamic filter building for a search in Mongoose.
I got an array containing various filters, and I would like to use them in this.mySchema.find ({QUERY}) as follows:
[
{ name: { '$eq': 'John' } },
{ surname: { '$regex': '.*t', '$options': 'i' } }
]
Now I would like to search by all filters as below
const query = this.customerModel.find(findFilters);
But I am getting the error below
Parameter "filter" to find() must be an object, got [object Object],[object Object]
I tried converting this to an object, but I'm getting something that I can't use either
{ ...findFilters }
Result:
{
'0': { name: { '$eq': 'John' } },
'1': { surname: { '$regex': '.*t', '$options': 'i' } }
}
I also tried this:
const result = {};
findFilters.forEach(e => result[e] = {});
But I got something that also doesn't work in Find and the filters don't work during the search
{ '[object Object]': {} }
So, how can I use my array of filters in the Find method?
You need to reduce() to a single object:
const filters = [
{ name: { '$eq': 'John' } },
{ surname: { '$regex': '.*t', '$options': 'i' } }
];
const filter = filters.reduce((a, v) => ({...a, ...v}), {});
console.log(filter);
Your result is an pending promise
you need to use an async function and use await:
const query = await this.customerModel.find(findFilters);
Or .then()
this.customerModel.find(findFilters).then(res => {
console.log(res);
})
I'm performing two MongoDB queries, and then I want to synchronize the resulting arrays, to make sure they are in the same order.
The first array is a set of (20) questions ids (this is the correct order):
q_id_arr: [
"5f86da2d37e3d200040ba523",
"5f86b6ce37e3d200040ba4c6",
"5ffc4abea04f3c0004e46cf3",
"5f86b66537e3d200040ba4c5",
"5f87f368554f370004ed17b4",
"5f86e48c37e3d200040ba53c",
"5ffc4dc4a04f3c0004e46d0b",
"5f86e19037e3d200040ba534",
"5f86aaa237e3d200040ba49b",
"5ffc479ba04f3c0004e46ce0",
"5f86b9dc37e3d200040ba4d2",
"5f85828e0e1bd30004361430",
"5f8700c937e3d200040ba548",
"5f86d81737e3d200040ba51c",
"5f8708d237e3d200040ba568",
"5f87060d37e3d200040ba55c",
"5f857dac0e1bd3000436141c",
"5f85703e0e1bd300043613ec",
"5f87e9d4554f370004ed178e",
"5f8073c04ad88e00041f015f"
]
The second array is a set of (20) results associated with the question ids:
team_trends: [
{
"_id":"5f87e9d4554f370004ed178e",
"positive":0.93,
"engaged":0.558
},
{
"_id":"5f86e19037e3d200040ba534",
"positive":0.585,
"engaged":0.567
},
{
"_id":"5f85828e0e1bd30004361430",
"positive":0.7,
"engaged":0.666
},
{
"_id":"5f8073c04ad88e00041f015f",
"positive":0.31,
"engaged":0.30999999999999994
},
{
"_id":"5f87f368554f370004ed17b4",
"positive":0.5449999999999999,
"engaged":0.57
},
{
"_id":"5f86b6ce37e3d200040ba4c6",
"positive":0.855,
"engaged":0.46599999999999997
},
{
"_id":"5f857dac0e1bd3000436141c",
"positive":0.92,
"engaged":0.524
},
{
"_id":"5f85703e0e1bd300043613ec",
"positive":0.15,
"engaged":0.39
},
{
"_id":"5f86aaa237e3d200040ba49b",
"positive":0.15000000000000002,
"engaged":0.584
},
{
"_id":"5f86b66537e3d200040ba4c5",
"positive":0.37,
"engaged":0.386
},
{
"_id":"5f86e48c37e3d200040ba53c",
"positive":0.615,
"engaged":0.548
},
{
"_id":"5ffc479ba04f3c0004e46ce0",
"positive":0.42000000000000004,
"engaged":0.583
},
{
"_id":"5f86b9dc37e3d200040ba4d2",
"positive":0.68,
"engaged":0.662
},
{
"_id":"5f86d81737e3d200040ba51c",
"positive":0.03,
"engaged":0.516
},
{
"_id":"5f87060d37e3d200040ba55c",
"positive":0.14,
"engaged":0.454
},
{
"_id":"5f86da2d37e3d200040ba523",
"positive":0.47,
"engaged":0.41500000000000004
},
{
"_id":"5f8708d237e3d200040ba568",
"positive":0.17,
"engaged":0.76
},
{
"_id":"5ffc4dc4a04f3c0004e46d0b",
"positive":0.395,
"engaged":0.53
},
{
"_id":"5ffc4abea04f3c0004e46cf3",
"positive":0.365,
"engaged":0.679
},
{
"_id":"5f8700c937e3d200040ba548",
"positive":0.93,
"engaged":0.6980000000000001
}
]
I want to reorganize team_trends into the same order as q_id_arr
Here is the code I'm using (following this SO Answer):
let c = [];
q_id_arr.forEach((q_oid => c.push(team_trends.find((obj => obj._id == q_oid)))));
However when I print console.log("the result of c"+ c) I get this result:
the result of c: [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]
Is this the right approach? Any suggestions are appreciated!
More Details:
Before this step I acquired the q_id_arr through mapping over an aggregate result, like this:
let q_id_arr = await user_trends.map(({ question_oid }) => question_oid)
When I tested console.log(typeof q_id_arr) it returned object.
How can I sort through the object??
Final code that fixed the issue.
user_trends.forEach((user => c.push(team_trends.find((obj => obj._id.toString() === user.question_oid.toString())))));
A couple of points to note here:
If you are using mongoose then it already returns an array from the aggregate function.
Mongoose uses the MongoDB NodeJs native driver at its core. In core driver ObjectId has a function .equals(otherId). It is always best to use this function for id comparisons.
References:
Comparing mongoose _id and strings
.aggregate(...).toArray is not a function
https://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html#equals
You can try this using the arrays map method:
let sorted_team_trends = q_id_arr.map( q => team_trends.find(t => t._id === q) );
Assuming the two arrays are defined as fields like this:
let q_id_arr = [
"5f86da2d37e3d200040ba523",
"5f86b6ce37e3d200040ba4c6",
"5ffc4abea04f3c0004e46cf3",
...
];
let team_trends = [
{
"_id" : "5f87e9d4554f370004ed178e",
"positive" : 0.93,
"engaged" : 0.558
},
{
"_id" : "5f86e19037e3d200040ba534",
"positive" : 0.585,
"engaged" : 0.567
},
...
]
Using TypeScript
Below is an array of objects & I want to map this in to a new object as provided below . (see the expected result)
// input array
const getPostAPI =
[
{
get: '1234',
post: 'abcd',
},
{
get: '3423',
post: 'dfcv',
},
{
get: '1234',
post: 'iucv',
},
{
get: '1234',
post: 'oipl',
},
{
get: '3423',
post: 'ffgf',
},
{
get: '4567',
post: 'tyui',
},
]
from the above array of objects I want to map the post values as an array for repeating get values.
Below I've provided the exptected result.
// output object
const exptectedResult = {
'1234': ['abcd',
'iucv',
'oipl',
'1234',],
'3423': ['dfcv',
'ffgf'],
'4567': ['tyui']
}
Following is what I've tried. But it is overwriting some of the values.
i.e., I'm not getting the exact number of elements in the array of corresponding get key. (it is one less than actual)
this.getPostMap = this.getPostAPI.reduce(
(map, api) => ({
...map,
[api.get]: map[api.get]
? [...map[api.get], api.post]
: [] || [],
}),
{}
);
This simple piece of code will work very smoothly.
getPostAPI.reduce((acc, el)=>{
(acc[el.get] = acc[el.get] || []).push(el.post)
return acc
}, {})
That is quite a terrifying and unreadable block of code to do something that can be very simple. For example:
const getPostAPI = [{
get: '1234',
post: 'abcd',
},
{
get: '3423',
post: 'dfcv',
},
{
get: '1234',
post: 'iucv',
},
{
get: '1234',
post: 'oipl',
},
{
get: '3423',
post: 'ffgf',
},
{
get: '4567',
post: 'tyui',
},
];
const expectedResult = getPostAPI.reduce((map, {get,post}) =>
(map[get] = map[get] || []).push(post) && map,
{});
console.log(expectedResult);
Your Problem is that when the get property is undefined, you actually want to fulfill it with the first post instead of an empty object :
this.getPostMap = this.getPostAPI.reduce(
(map, api) => ({
...map,
[api.get]: map[api.get]
? [...map[api.get], api.post]
: [api.post],
}),
{}
);
I want to normalise the responses I receive from an API. A typical response could look something like this:
// Get all projects
{data:[
{
id: 1
...
team:{
data: {
id:15
...
}
}
},
{
id:2,
....
},
{
id:3,
...
}
]}
How do I write my schemas so that it removes the 'data' container?
Currently, my schema looks like:
export const project = new schema.Entity('projects', {
team: team, // team omitted
},
{
processStrategy: (value, parent, key) => parent.data
}
)
export const arrayOfProjects = new schema.Array(project)
And I am using it like:
const normalizedProjects = normalize(jsonResponse, arrayOfProjects)
normalizedProjects then looks like this:
{
entities:{
projects:{
undefined:{
0:{
team:{
data:{
id:15,
...
}
}
},
1:{...},
2:{...}.
...
50:{...},
}
}
},
result:[] // length is 0
}
I'm not sure why the list of projects is contained in 'undefined', either?
I also use json_api schema.
How about like this?
const projectsSchema = new schema.Entity('projects', {}, {
processStrategy: processStrategy
});
export const processStrategy = (value, parent, key) => {
const attr = value.attributes;
delete value.attributes;
return { ...value, ...attr };
};
export const fetchProjectsSchema = {
data: [projectsSchema]
}
Each of your entity schema that you want to have the data omitted (or anything else fundamentalyl changed) needs to include a processStrategy that you write to remove or change any data. (see more examples in the tests)