Add a Object into state with array of Object by Redux - javascript

when my backend send a payload with value:
Object {
"__v": 0,
"_id": "621ef5eec33b5c6d9d184563",
"category": "621ef5e8c33b5c6d9d18455e",
"createdAt": "2022-03-02T04:43:26.834Z",
"description": "",
"name": "Hair and Nails",
"price": 50,
"updatedAt": "2022-03-02T04:43:26.834Z",
},
How to add this Object to my serviceReducer
const initialState = {
isLoading: false,
error: false,
serviceCategories: [], //! serviceCategories is a Array
};
first of all, I map serviceCategories and selected serviceCategories that I need
return {
...state,
serviceCategories: state.serviceCategories.map((serviceCateogory) => {
return serviceCateogory._id === action.payload.category
? serviceCateogory //! here How I to add that object to services of serviceCateogory
: serviceCateogory;
}),
// ),
};
this is Structure of serviceCategories:
[
Object {
"__v": 0,
"_id": "621ef5e8c33b5c6d9d18455e",
"createdAt": "2022-03-02T04:43:20.754Z",
"name": "Category1",
"services": Array [
Object {
"__v": 0,
"_id": "621ef5eec33b5c6d9d184563",
"category": "621ef5e8c33b5c6d9d18455e",
"createdAt": "2022-03-02T04:43:26.834Z",
"description": "",
"name": "Service1",
"price": 50,
"updatedAt": "2022-03-02T04:43:26.834Z",
},
Object {
"__v": 0,
"_id": "621ef7d1c33b5c6d9d1845b1",
"category": "621ef5e8c33b5c6d9d18455e",
"createdAt": "2022-03-02T04:51:29.262Z",
"description": "",
"name": "Service2",
"price": 50,
"updatedAt": "2022-03-02T04:51:29.262Z",
},
],
"updatedAt": "2022-03-02T05:08:35.520Z",
},
Object {
"__v": 0,
"_id": "621ef5e8c33b5c6d9d18455e",
"createdAt": "2022-03-02T04:43:20.754Z",
"name": "Category2",
....
]

You need to first findIndex of the specific category from the redux state and then append the service in it.
Like:
let categories=[...state.serviceCategories];
let catIndex=categories.findIndex((item)=>item._id===action.payload.category);
if(catIndex!=-1) categories[catIndex].services.push(object); // append object (service) as you wish.
state.serviceCategories=categories;

Related

Nested comments in comments

const post = {
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [],
"_id": "60d6ab9207c0a573786a9e65",
"userId": "60c418582f7066090ced4a51",
"content": "good post 3",
"createdAt": "2021-06-26T04:22:42.337Z",
"updatedAt": "2021-06-26T04:22:42.337Z",
"__v": 0
}
],
"_id": "60d6962cee10aa73f820b974",
"userId": "60c418582f7066090ced4a51",
"content": "good post 2",
"createdAt": "2021-06-26T02:51:24.111Z",
"updatedAt": "2021-06-26T04:22:42.622Z",
"__v": 0
},
{
"comments": [],
"_id": "60d705784ab01c354cf7f445",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "Comment deleted by User",
"createdAt": "2021-06-26T10:46:16.813Z",
"updatedAt": "2021-06-26T12:29:06.398Z",
"__v": 0
},
{
"comments": [],
"_id": "60d706febcba957b04406547",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "yes it is a good post 1 from alexane Updated",
"createdAt": "2021-06-26T10:52:46.679Z",
"updatedAt": "2021-06-26T12:17:58.879Z",
"__v": 0
}
],
"_id": "60d695b4ee10aa73f820b973",
"userId": "60c418582f7066090ced4a51",
"content": "good post 1",
"createdAt": "2021-06-26T02:49:24.426Z",
"updatedAt": "2021-06-26T12:30:44.872Z",
"__v": 0
}
],
"_id": "60d68e32dff84439a4d3b191",
"userId": "60c418582f7066090ced4a51",
"content": "good post",
"createdAt": "2021-06-26T02:17:22.625Z",
"updatedAt": "2021-06-26T02:49:24.820Z",
"__v": 0
},
{
"comments": [
{
"comments": [],
"_id": "60d6c2d917d0b12be44742d2",
"userId": "60c418582f7066090ced4a51",
"content": "nice post 1",
"createdAt": "2021-06-26T06:02:01.420Z",
"updatedAt": "2021-06-26T06:02:01.420Z",
"__v": 0
}
],
"_id": "60d6bebf17d0b12be44742d1",
"userId": "60c418582f7066090ced4a51",
"content": "nice post",
"createdAt": "2021-06-26T05:44:31.436Z",
"updatedAt": "2021-06-26T06:02:01.676Z",
"__v": 0
}
]
}
I have a deep nested object which I got from mongoose.
a. How do I iterate through this deep nested objects? Should I use a recursion and loop because I can't seem to wrap my head around this? I manage to iterate through to the end of the comments . I managed to come up with something as brute force as below but i am kinda stuck here.
const findObject = (obj) => {
for (let i = 0; i < obj.comments.length; i++) {
const element = obj.comments[i];
for (let y = 0; y < element.comments.length; y++) {
const newElements = element.comments[y];
for (let z = 0; z < newElements.comments.length; z++) {
const newElementsZ = newElements.comments[z];
console.log(newElementsZ)
}
}
}
};
b. How to calculate the total number of comments, in this case it is 8 comments ?
Thank you very much.
You can use recursion to do it. (since it has indefinite number of layers, write all the nested loops doesn't really scale).
const post = { "comments": [{ "comments": [{ "comments": [{ "comments": [{ "comments": [], "_id": "60d6ab9207c0a573786a9e65", }], "_id": "60d6962cee10aa73f820b974", }, { "comments": [], "_id": "60d705784ab01c354cf7f445", }, { "comments": [], "_id": "60d706febcba957b04406547", } ], "_id": "60d695b4ee10aa73f820b973", }], "_id": "60d68e32dff84439a4d3b191", }, { "comments": [{ "comments": [], "_id": "60d6c2d917d0b12be44742d2", }], "_id": "60d6bebf17d0b12be44742d1", } ] }
function CountComment(data){
let count = 0
for(let c of data.comments){
++count
count+=CountComment(c)
}
return count
}
console.log(CountComment(post))
Or you can use stack/queue based approach if the recursion depth cause problem.
const post = { "comments": [{ "comments": [{ "comments": [{ "comments": [{ "comments": [], "_id": "60d6ab9207c0a573786a9e65", }], "_id": "60d6962cee10aa73f820b974", }, { "comments": [], "_id": "60d705784ab01c354cf7f445", }, { "comments": [], "_id": "60d706febcba957b04406547", } ], "_id": "60d695b4ee10aa73f820b973", }], "_id": "60d68e32dff84439a4d3b191", }, { "comments": [{ "comments": [], "_id": "60d6c2d917d0b12be44742d2", }], "_id": "60d6bebf17d0b12be44742d1", } ] }
function CountComment(post){
let nodes = [post]
let count = 0
while(nodes.length){
let node = nodes.pop()
++count
for(let c of node.comments)
nodes.push(c)
}
return count-1 //remove post itself
}
console.log(CountComment(post))

mongoDB - How do master-detail structure grouped detail collection specific fields summary

In a mongodb database with a master-detail structure, how do I ensure that the data in the detail table is grouped according to the status area while querying the master table. For example ...
Master, Row, Job, Fields, [Detail Status Grouped Count / Summary Object]
Edited:
sms_jobs collection example data is :
// 1
{
"_id": NumberInt("1"),
"company": {
"id": NumberInt("1"),
"name": "",
"sms_gateway_id": NumberInt("1"),
"sms_gateway_parameters": {
"password": "",
"username": ""
},
"is_active": true
},
"source_type": "form",
"source": {
"id": NumberInt("2"),
"company_id": NumberInt("1"),
"title": "Import Data Demo",
"description": "<p>Üst Açıklama</p>",
"footer_description": "<p>Alt Açıklama</p>",
"thanks_message": "Katiliminiz icin tesekkur ederiz.",
"sms_message": "{company} KVKK Aydinlatma Metni ve Acik Riza Onayi icin Dogrulama Kodunuz : {code} ( {form_link} )",
"digest": null,
"ts_digest": null,
"is_active": true,
"is_locked": false
},
"description": "Import Data Demo",
"status": "waiting",
"job_count": NumberInt("22145"),
"updated_at": ISODate("2020-08-15T17:00:49.252Z"),
"created_at": ISODate("2020-08-15T16:59:10.899Z")
}
sms_job_details collection example data is :
// 1
{
"_id": NumberInt("221462"),
"sms_job_id": NumberInt("1"),
"gsm": "",
"schedule_at": ISODate("2020-08-15T19:41:44.827Z"),
"raw_message": "{name} {surname} {id_number} {form_link} {reject_link}",
"message": "",
"status": "waiting", // I want this statuses grouped count my master table rows in line object
"expire_at": "2020-08-18T17:40:44.967Z",
"updated_at": ISODate("2020-08-15T18:45:53.727Z"),
"created_at": ISODate("2020-08-15T18:45:53.727Z")
}
// 2
{
"_id": NumberInt("221463"),
"sms_job_id": NumberInt("1"),
"gsm": "",
"schedule_at": ISODate("2020-08-15T19:41:44.827Z"),
"raw_message": "{name} {surname} {id_number} {form_link} {reject_link}",
"message": "",
"status": "failed", // I want this statuses grouped count my master table rows in line object
"expire_at": "2020-08-18T17:40:44.967Z",
"updated_at": ISODate("2020-08-15T18:45:53.727Z"),
"created_at": ISODate("2020-08-15T18:45:53.727Z")
}
// 3
{
"_id": NumberInt("221464"),
"sms_job_id": NumberInt("1"),
"gsm": "",
"schedule_at": ISODate("2020-08-15T19:41:44.827Z"),
"raw_message": "{name} {surname} {id_number} {form_link} {reject_link}",
"message": "",
"status": "success", // I want this statuses grouped count my master table rows in line object
"expire_at": "2020-08-18T17:40:44.967Z",
"updated_at": ISODate("2020-08-15T18:45:53.727Z"),
"created_at": ISODate("2020-08-15T18:45:53.727Z")
}
I experimented for approximately 4-5 hours. I could get the closest result with the following query.
db.getCollection("sms_jobs").aggregate([{
$lookup: {
from: "sms_job_details",
localField: "_id",
foreignField: "sms_job_id",
as: "data"
}
}, {
$unwind: "$data"
}, {
$group: {
_id: {
id: "$_id",
status: "$data.status"
},
qty: {
$sum: 1
}
}
}, {
$project: {
_id: "$_id.id",
qty: 1,
status: "$_id.status"
}
}])
And get this result :
// 1
{
"qty": 22145,
"_id": NumberInt("4"),
"status": "success"
}
// 2
{
"qty": 1,
"_id": NumberInt("3"),
"status": "success"
}
// 3
{
"qty": 22142,
"_id": NumberInt("1"),
"status": "success"
}
// 4
{
"qty": 1,
"_id": NumberInt("1"),
"status": "failed"
}
// 5
{
"qty": 2,
"_id": NumberInt("1"),
"status": "waiting"
}
// 6
{
"qty": 1,
"_id": NumberInt("3"),
"status": "failed"
}
// 7
{
"qty": 3,
"_id": NumberInt("3"),
"status": "waiting"
}
What do I want ?
The query result I want is as follows.
// 1
{
"_id": NumberInt("1"),
"company": {
"id": NumberInt("1"),
"name": "",
"sms_gateway_id": NumberInt("1"),
"sms_gateway_parameters": {
"password": "",
"username": ""
},
"is_active": true
},
"source_type": "form",
"source": {
"id": NumberInt("2"),
"company_id": NumberInt("1"),
"title": "Import Data Demo",
"description": "<p>Üst Açıklama</p>",
"footer_description": "<p>Alt Açıklama</p>",
"thanks_message": "Katiliminiz icin tesekkur ederiz.",
"sms_message": "{company} KVKK Aydinlatma Metni ve Acik Riza Onayi icin Dogrulama Kodunuz : {code} ( {form_link} )",
"digest": null,
"ts_digest": null,
"is_active": true,
"is_locked": false
},
"description": "Import Data Demo",
"status": "waiting",
"job_count": NumberInt("22145"),
"updated_at": ISODate("2020-08-15T17:00:49.252Z"),
"created_at": ISODate("2020-08-15T16:59:10.899Z"),
// Added part...
"status_countes": {
"success": NumberInt("20"),
"failed": NumberInt("2"),
"waiting": NumberInt("11"),
"canceled": NumberInt("0"),
"total": NumberInt("33")
},
}
Thank you in advance for your help...

Sorting a nest object by datetime not working as expected

I am having some trouble sorting a nested object by its timestamp. I was hoping for some help...
This is what the object looks like and what I have so far...
useEffect(() => {
if (realtime.length) {
let unorderedmessage = realtime.concat(messages);
const orderedMessages = unorderedmessage
.slice()
.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt));
setMessages(orderedMessages);
}
}, [realtime]);
[
Object {
"_id": "a16edcb7-17e1-46ea-b8ce-5ec312d5eb6c",
"createdAt": 2020-04-23T01:51:48.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "2–> Olivia to Mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "5ef28d42-6f7c-45eb-a5e1-59ca700f56b7",
"createdAt": 2020-04-23T02:01:52.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "4–> Olivia to mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "1e07873f-f010-4e9d-be17-9bcb7793695b",
"createdAt": 2020-04-23T02:02:06.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"lTONqS9O00PhkxwHD2EYs05EMwu2",
],
"text": "5–> mike to Olivia",
"user": Object {
"_id": "OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
"avatar": "123",
},
},
Object {
"_id": "5fecafc3-c608-4156-b88c-f6c57e8e9977",
"createdAt": 2020-04-23T02:01:20.000Z,
"index": 1,
"key": "cid-1710824786",
"receiver": Array [
"OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
],
"text": "3–> Olivia to Mike",
"user": Object {
"_id": "lTONqS9O00PhkxwHD2EYs05EMwu2",
"avatar": "123",
},
},
Object {
"_id": "fae07391-9968-432a-8a39-0c1be0d7e9ac",
"createdAt": 2020-04-23T01:51:41.000Z,
"index": 0,
"key": "cid-1710824786",
"receiver": Array [
"lTONqS9O00PhkxwHD2EYs05EMwu2",
],
"text": "1–> mike to Olivia",
"user": Object {
"_id": "OUloNoRKdIeyhNFcAAB6VLrZ5yH2",
"avatar": "123",
},
},
],
The messages are still coming in out of order so I am sure I am writing the sort function incorrectly. I am going through these tutorials and docs and it seems to be correct....
https://www.geeksforgeeks.org/sort-an-object-array-by-date-in-javascript/
https://flaviocopes.com/how-to-sort-array-by-date-javascript/
How to sort an array by a date property
I have also tried explicitly writing out the function like:
let unorderedmessage = realtime.concat(messages);
unorderedmessage.sort(function(a, b) {
return new Date(b.createdAt) - new Date(a.createdAt);
});
setMessages(unorderedmessage);
but still no luck. Can anyone see what I am doing wrong?
Works like a charm for me: https://playcode.io/583725/
Cannot be the issue in your Object variable definition?
You don't need to specify Object, this is enough:
const myNewObject = {firstKey: 'firstValue', secondKeys: 'secondValue'}
But if you do, you have to create it with new keyword:
const myNewObject = new Object {firstKey: 'firstValue', secondKeys: 'secondValue'}

Incorrect output when using lodash on results returned by mongoose

I have a result set returned from a mongodb query and am using lodash to reformat it. I am trying to convert the array of objects into a single object. The problem is when I use lodash on the result set, I get unexpected output.
NOTE: Running the snippet on codepen/codesandbox gives correct output, but not when used directly from mongoose results.
Mongoose Query
try {
const petInfo = await pets.find({ userId: user_id, petId: pet_id })
.select({
"_id": 0,
"createdAt": 0,
"updatedAt": 0,
"__v": 0
});
if(!petInfo) {
return res.status(400).json({ message: "FAILED_TO_FETCH_PET_INFO" });
}
let newObj = _.reduce(petInfo, (acc, cur)=> { return _.assign(acc, cur) }, {});
return res.status(200).json(newObj);
}
catch (error) {
req.errorMsg = error.message; // Log actual error
return res.status(500).json({ message: "SOME_ERROR_OCCURRED" });
}
Result from mongoose find query (petInfo)
[
{
"age": {
"days": "",
"months": "",
"years": ""
},
"userId": "45422605180207851194",
"name": "Oscar",
"gender": "FEMALE",
"type": "Dog",
"breed": "",
"weight": "",
"spayOrNeuter": false,
"petId": "KSVv7yJLnUWX3n"
}
]
Lodash snippet
let newObj = _.reduce(petInfo, (acc, cur)=> { return _.assign(acc, cur) }, {});
return res.status(200).json(newObj);
Result after modification
{
"$__": {
"strictMode": true,
"selected": {
"_id": 0,
"createdAt": 0,
"updatedAt": 0,
"__v": 0
},
"getters": {
"age": {
"days": "",
"months": "",
"years": ""
}
},
"wasPopulated": false,
"scope": {
"age": {
"days": "",
"months": "",
"years": ""
},
"userId": "45422605180207851194",
"name": "Oscar",
"gender": "FEMALE",
"type": "Dog",
"breed": "",
"weight": "",
"spayOrNeuter": false,
"petId": "KSVv7yJLnUWX3n"
},
"activePaths": {
"paths": {
"userId": "init",
"petId": "init",
"name": "init",
"gender": "init",
"type": "init",
"breed": "init",
"age.days": "init",
"age.months": "init",
"age.years": "init",
"weight": "init",
"spayOrNeuter": "init"
},
"states": {
"ignore": {},
"default": {},
"init": {
"userId": true,
"name": true,
"gender": true,
"type": true,
"breed": true,
"age.days": true,
"age.months": true,
"age.years": true,
"weight": true,
"spayOrNeuter": true,
"petId": true
},
"modify": {},
"require": {}
},
"stateNames": [
"require",
"modify",
"init",
"default",
"ignore"
]
},
"pathsToScopes": {},
"cachedRequired": {},
"session": null,
"$setCalled": {},
"emitter": {
"_events": {},
"_eventsCount": 0,
"_maxListeners": 0
},
"$options": {
"skipId": true,
"isNew": false,
"willInit": true
},
"nestedPath": "age"
},
"isNew": false,
"_doc": {
"age": {
"days": "",
"months": "",
"years": ""
},
"userId": "45422605180207851194",
"name": "Oscar",
"gender": "FEMALE",
"type": "Dog",
"breed": "",
"weight": "",
"spayOrNeuter": false,
"petId": "KSVv7yJLnUWX3n"
},
"$locals": {},
"$init": true
}
The reason for this is because mongoose doesn't return the object you think it does. Instead, it returns a 'mongoose' object with a bunch of methods ect ect. There are 2 ways around this, either call .lean() on your query or toJSON() on the result to sanitize result into normal js object.
.lean()
const petInfo = await pets.find({ userId: user_id, petId: pet_id })
.select({
"_id": 0,
"createdAt": 0,
"updatedAt": 0,
"__v": 0
}).lean();
.toJSON()
const petInfo = await pets.find({ userId: user_id, petId: pet_id })
.select({
"_id": 0,
"createdAt": 0,
"updatedAt": 0,
"__v": 0
}).lean();
const parsed = petInfo.toJSON()
Your query will return the result set as document objects instead of plain objects, which is why you get all the additional information like strictMode, getters, etc.
You could use the lean() function in order to get plain objects only (see https://mongoosejs.com/docs/tutorials/lean.html), e.g.:
const petInfo = await pets.find({ userId: user_id, petId: pet_id })
.select({
"_id": 0,
"createdAt": 0,
"updatedAt": 0,
"__v": 0
}).lean();

sequelize include returns only one result

I have a Users table and a Groups table, when I retrieve a single user, I want to get a list of all the groups that user belongs to. I created a joins table named GroupUsers and it has userId and groupId on it, this is how I know that a user belongs to a group. Now, when I try to get the list of groups a user belongs to using the sequelize include on find, it only returns the first match, if the user belongs to various groups. How do I solve this?
Users controller
return models.Users
.find({
include: [{
model: models.Groups,
as: 'groups',
limit: null,
required: false
}],
where: { username }
})
Returns this:
{
"id": 1,
"username": "John",
"phone": "xxxxxxxx",
"email": "john#email.com",
"createdAt": "2017-07-16T20:14:04.744Z",
"updatedAt": "2017-07-16T20:14:04.744Z",
"groups": [
{
"id": 1,
"name": "Test Group",
"type": "Public",
"createdAt": "2017-07-16T20:13:18.392Z",
"updatedAt": "2017-07-16T20:13:18.392Z",
"GroupUsers": {
"userId": 1,
"groupId": 1,
"last_seen": null,
"createdAt": "2017-07-16T20:14:27.903Z",
"updatedAt": "2017-07-16T20:14:27.903Z"
}
}
]
}
Instead of this:
{
"id": 1,
"username": "John",
"phone": "xxxxxxxx",
"email": "john#email.com",
"createdAt": "2017-07-16T20:14:04.744Z",
"updatedAt": "2017-07-16T20:14:04.744Z",
"groups": [
{
"id": 1,
"name": "Test Group",
"type": "Public",
"createdAt": "2017-07-16T20:13:18.392Z",
"updatedAt": "2017-07-16T20:13:18.392Z",
"GroupUsers": {
"userId": 1,
"groupId": 1,
"last_seen": null,
"createdAt": "2017-07-16T20:14:27.903Z",
"updatedAt": "2017-07-16T20:14:27.903Z"
}
},
{
"id": 2,
"name": "Test Group 2",
"type": "Public",
"createdAt": "2017-07-16T20:13:18.392Z",
"updatedAt": "2017-07-16T20:13:18.392Z",
"GroupUsers": {
"userId": 1,
"groupId": 2,
"last_seen": null,
"createdAt": "2017-07-16T20:14:27.903Z",
"updatedAt": "2017-07-16T20:14:27.903Z"
}
}
]
}
I'm sure I'm doing something wrong somewhere I just don't know where, that same thing may also be the cause of sequelize including the joins table in the result: GroupUsers
It appears that in my associations, I did:
Users.belongsToMany(models.Groups, {
through: 'GroupUsers',
as: 'groups',
foreignKey: 'groupId'
});
Instead of :
Users.belongsToMany(models.Groups, {
through: 'GroupUsers',
as: 'groups',
foreignKey: 'userId'
});
Note the foreignKey attribute
And as for the GroupUsers object that is also returned, I removed that by doing:
include: [{
model: models.Groups,
as: 'groups',
attributes: ['id', 'name'],
through: { attributes: [] }
}]
Note the through key which has attributes set to an empty array.

Categories

Resources