Nested comments in comments - javascript

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))

Related

Add a Object into state with array of Object by Redux

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;

Data structure of Threaded comments in mongoose and Node Js

{
"post": {
"img": "",
"likes": [
"60c418582f7066090ced4a51"
],
"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
},
{
"comments": [
{
"comments": [],
"_id": "60d87e7df43fed7e4079875e",
"userId": "60c15ac41ed8da1ab4efe7f3",
"content": "awesome post 1",
"createdAt": "2021-06-27T13:34:53.192Z",
"updatedAt": "2021-06-27T13:34:53.192Z",
"__v": 0
}
],
"_id": "60d87cb4f43fed7e4079875d",
"userId": "60c418582f7066090ced4a51",
"content": "awesome post",
"createdAt": "2021-06-27T13:27:16.299Z",
"updatedAt": "2021-06-27T13:34:53.468Z",
"__v": 0
}
],
"_id": "60c5a23eb37b425a00968fa9",
"userId": "60c418582f7066090ced4a51",
"description": "This is a sample Post 2",
"createdAt": "2021-06-13T06:14:22.196Z",
"updatedAt": "2021-06-27T13:27:16.577Z",
"__v": 0
}
}
I have a threaded comments for a single post which I recursively autopopulated using Mongoose (the code can be found below ). Is it correct to assume the above data structure is a Tree ? If yes, what kind of tree data structure would be the best to implement a a threaded comments to do basic crud such as insert , edit and delete.
//Comment.js
const mongoose = require('mongoose')
const { Schema } = mongoose
const commentObj = {
userId: {
type: mongoose.Types.ObjectId,
ref: "User",
required: true
},
content: {
type: String,
min: 6,
required: true
},
comments: [
{ type: Schema.Types.ObjectId, ref: 'Comment' }
],
}
const commentSchema = new Schema(commentObj, { timestamps: true });
const autoPopulateChildren = function (next) {
this.populate('comments');
next();
};
commentSchema
.pre('findOne', autoPopulateChildren)
.pre('find', autoPopulateChildren)
const Comment = mongoose.model('Comment', commentSchema);
module.exports = Comment
//Post.js
const mongoose = require('mongoose')
const { Schema } = mongoose
const postObj = {
userId: {
type: mongoose.Types.ObjectId,
ref: "User",
required: true
},
description: {
type: String,
min: 6,
required: true
},
img: {
type: String,
default: '',
},
likes: [
{
type: mongoose.Types.ObjectId,
ref: "User"
}
],
comments: [
{
type: mongoose.Types.ObjectId,
ref: "Comment",
}
]
}
const postSchema = new Schema(postObj, { timestamps: true });
const Post = mongoose.model('Post', postSchema);
module.exports = Post
Thank you.

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'}

How can I get count of the Documents and filter them in efficient way? (mongoose)

I'm implementing search function that is simply find document in mongoDB. I want to .skip(x) and .limit(x) on result to simulate paging result, but can I get total count of document (before skip and limit) and get filtered result at once?
Code that produce Expected Output :
db.Datas.find({ type: "Unknown" })
.then((result) => {
let count = result.length;
db.Datas.find({ type: "Unknown" })
.sort({ createdAt: -1 })
.skip((req.query.page - 1) * 10)
.limit(10)
.then((res) => {
res.json({ count: count, result: res });
});
})
.catch((err) => {});
But querying twice it somehow annoying, and it might be slow at large database.
I tried something like find({}).then(x => { ... }).sort(...) ... but isn't working because it only returns Promise.
How can I do this things in efficient way?
or is just getting whole documents and skip, limit with JS-way (using .splice, or etc..) will be faster and efficient?
You can use $facet aggregation to achieve this.
db.Datas.aggregate([
{
$match: {
"type": "Unknown"
}
},
{
$sort: {
createdAt: -1
}
},
{
$facet: {
totalRecords: [
{
$count: "total"
}
],
data: [
{
$skip: 0
},
{
$limit: 5
}
]
}
}
])
Playground
Let's say you have these documents:
db={
"Datas": [
{
"_id": "5e390fc33285e463a0799689",
"type": "Known",
"createdAt": "2020-02-04T06:31:31.311Z",
"__v": 0
},
{
"_id": "5e390fd03285e463a079968a",
"type": "Known",
"createdAt": "2020-02-04T06:31:44.190Z",
"__v": 0
},
{
"_id": "5e390fda3285e463a079968b",
"type": "Unknown",
"createdAt": "2020-02-04T06:31:54.248Z",
"__v": 0
},
{
"_id": "5e390fdf3285e463a079968c",
"type": "Unknown",
"createdAt": "2020-02-04T06:31:59.993Z",
"__v": 0
},
{
"_id": "5e390fec3285e463a079968d",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:12.336Z",
"__v": 0
},
{
"_id": "5e390ffd3285e463a079968e",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:29.670Z",
"__v": 0
},
{
"_id": "5e3910163285e463a079968f",
"type": "Unknown",
"createdAt": "2020-02-04T06:32:54.131Z",
"__v": 0
},
{
"_id": "5e3910213285e463a0799690",
"type": "Unknown",
"createdAt": "2020-02-04T06:33:05.166Z",
"__v": 0
}
]
}
Response will be like this:
[
{
"data": [
{
"__v": 0,
"_id": "5e3910213285e463a0799690",
"createdAt": "2020-02-04T06:33:05.166Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e3910163285e463a079968f",
"createdAt": "2020-02-04T06:32:54.131Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390ffd3285e463a079968e",
"createdAt": "2020-02-04T06:32:29.670Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390fec3285e463a079968d",
"createdAt": "2020-02-04T06:32:12.336Z",
"type": "Unknown"
},
{
"__v": 0,
"_id": "5e390fdf3285e463a079968c",
"createdAt": "2020-02-04T06:31:59.993Z",
"type": "Unknown"
}
],
"totalRecords": [
{
"total": 6
}
]
}
]
As you see, we got the total records with the filtered, sorted, skipped and limited data.

Javascript how to add and remove JSON element which is on 2 level deep

I googled and monkey around a lot on how to remove elements from my JSON object.
Here is my simplified JSON to illustrate my requirement.
bundle:
{
"resourceType": "Bundle",
"meta": {
"lastUpdated": "2017-10-06T04:42:22.411Z"
},
"type": "searchset",
"total": "0",
"entry": [
{
"_id": "59d5739e668e9e3fd29aeb0d",
"resource": {
"id": "59d5739e668e9e3fd29aeb0d"
},
"__v": 0
},
{
"_id": "59d6a3fae4b45d50c5ffd4f7",
"resource": {
"id": "59d6a3fae4b45d50c5ffd4f7"
},
"__v": 0
},
{
"_id": "59d6a831e4b45d50c5ffd4fa",
"resource": {
"id": "59d6a831e4b45d50c5ffd4fa"
},
"__v": 0
}
]
}
How to remove ALL entry._id and entry.__v?
I tried these, but not working.
delete bundle.meta; <-- meta is on level 1, it works.
delete bundle.entry._id; <-- not working. The _id under entry
delete bundle.__v; <-- not working. The __v is also under entry
How can I add a new element under each entry such as "fullname" as below
My desired result - remove '_id' and '__v', then add 'fullname' to the entry[]:
{
"resourceType": "Bundle",
"meta": {
"lastUpdated": "2017-10-06T04:42:22.411Z"
},
"type": "searchset",
"total": "0",
"entry": [
{
"fullname": "Apple",
"resource": {
"id": "59d5739e668e9e3fd29aeb0d",
}
},
{
"fullname": "Orange",
"resource": {
"id": "59d6a3fae4b45d50c5ffd4f7"
},
}, ......
I have tried many ways and googled a lot. Thanks for the help!
Thanks Vivek for the answer. It works.
for (var i = 0; i < bundle.entry.length; i++) {
delete bundle.entry[i]._id;
delete bundle.entry[i].__v;
bundle.entry[i].fullname = "Test";
}
Please try the code below. Tested it can help you.
var object1 = {
"resourceType": "Bundle",
"meta": {
"lastUpdated": "2017-10-06T04:42:22.411Z"
},
"type": "searchset",
"total": "0",
"entry": [
{
"_id": "59d5739e668e9e3fd29aeb0d",
"resource": {
"id": "59d5739e668e9e3fd29aeb0d",
},
"__v": 0
},
{
"_id": "59d6a3fae4b45d50c5ffd4f7",
"resource": {
"id": "59d6a3fae4b45d50c5ffd4f7"
},
"__v": 0
},
{
"_id": "59d6a831e4b45d50c5ffd4fa",
"resource": {
"id": "59d6a831e4b45d50c5ffd4fa"
},
"__v": 0
}
]
};
var array1=['Apple','Orange','Gava']
function a(){
for(var i=0;i<object1.entry.length;i++){
delete object1.entry[i]._id;
delete object1.entry[i].__v;
object1.entry[i].fullname = array1[i];
}
console.log(object);
}
bundle.entry is an Array. :)
delete _id of first element:
delete bundle.entry[0]._id
delete _id and __v of all element:
bundle.entry = bundle.entry.map(function(entry){
var newEntry = {
resource: entry.resource,
fullname: "fullname here"
};
return newEntry;
});
const fullNameList = ['Apple', 'Orange', 'Guava']
delete bundle.meta
bundle.entry = bundle.entry.map((item, index) => {
const {__v, _id, ...restObj } = item;
restObj.fullname = fullNameList[index]
return restObj;
})
mind that the fullNameList's length and the bundle.entry's length must be the same
You can use the map function and remove the keys from the object, and add keys in the same function, as shown below:
var data = {
"resourceType": "Bundle",
"meta": {
"lastUpdated": "2017-10-06T04:42:22.411Z"
},
"type": "searchset",
"total": "0",
"entry": [
{
"_id": "59d5739e668e9e3fd29aeb0d",
"resource": {
"id": "59d5739e668e9e3fd29aeb0d"
},
"__v": 0
},
{
"_id": "59d6a3fae4b45d50c5ffd4f7",
"resource": {
"id": "59d6a3fae4b45d50c5ffd4f7"
},
"__v": 0
},
{
"_id": "59d6a831e4b45d50c5ffd4fa",
"resource": {
"id": "59d6a831e4b45d50c5ffd4fa"
},
"__v": 0
}
]
}
var names = ['A','B','C'];
var counter = 0;
data.entry = data.entry.map(function(obj){
delete obj['_id']
delete obj['__v']
obj.fullname = names[counter]
counter++ ;
return obj
});
console.log(data);

Categories

Resources