get all children of specific parent in node js - javascript

I want to get all children of specific parent. I am new to node.js and not able to write recursive function to do this task
var roots = [1,2,6];
var documents = [
{
"parent_id":1
,childerens:[4,5]
}
,{
"parent_id":4
,childerens:[9]
}
,{
"parent_id":9
,childerens:[]
}
,{
"parent_id":5
,childerens:[3]
}
,{
"parent_id":3
,childerens:[]
}
]
roots.forEach(function (rootParentId) {
var allchilderens=getAllchild(rootParentId);
})
Here's an example of what I mean:
var allchilderens = getAllchild(1);
allchilderens == [4,5,9,3]

function findAllChildren(element,is_root,childerens) {
if(is_root==false&&element!=undefined){
childerens.push(element);
}
var doc = documents.find(o => o.parent_id === element);
if(doc["childerens"].length==0){
return [];
}
else{
doc["childerens"].forEach(function (element) {
findAllChildren(element,false,childerens);
})
}
}
var childerens=[];
console.log(findAllChildren(1,true,childerens));
console.log("childerens==>",childerens);

You really want to build a tree structure here as step one.
Each object should, instead of containing a list of children ids, it should contain the actual children. That way, when you want to get all children, you can traverse that tree.

You probably should consider revising your data structure here. Why not use an object, where the user id is the key (since it should be unique). Then you would just need to get those keys directly.
Having everything inside of an array is potentially bad, since you'd have to iterate through the array to find each child, which would have (at worst), a run time equal to the length of the array.

Related

making json array in a method

I am working on an angular application. In my component I have a method as follows:
createPath(node, currentPath = []){
if(node.parent !==null) {
return createPath(node.parent, [node.data.name, ...currentPath])
} else {
return [node.data.name, ...currentPath];
}
}
Here I am recursively calling the method till node.parent becomes null. If it becomes null it will just give me node.data.name. In my each node, I have id also, which I can access using node.data.id. I want to store it in array in following format:
[{
id:1, //can access using node.data.id
name:"myName" //can access using node.data.name. which I am getting in above method.
}
]
This is just example at runtime I can have n number of item, so I want to write a dynamic code which work
in all condition.
I want to modify my above code and make this data in this method only.How can I do that?
Is your array being returned as an array from another destination? Because currently this would work for one item, you should use forEach() and push them into the array, So you will have a new array entry, otherwise the first item will be taken into the list and that will be it.
Did you try this?
createPath(node, currentPath = []){
if(node.parent !== null) {
return createPath(node.parent, [{id: node.data.id, name: node.data.name}, ...currentPath])
} else {
return [{id: node.data.id, name: node.data.name}, ...currentPath];
}
}
Intialiase an array to store your json objects as follows:
array:any=[ ]
Wherever you want to create the array (for example above the return statement of else block) add the following lines:
this.array.push(
{
id: node.data.id,
name: node.data.name
}
)

Nesting related elements together parent/child

Let's say I have an array as so with objects:
[
{
"id": "5a97e047f826a0111b754beb",
"name": "Hogwarts",
"parentId": "5c7bf2191d41c810b2ad6186",
"childrenIds": []
},
{
"id": "5c7bf2191d41c810b2ad6186",
"name": "Defense Against The Dark Arts",
"parentId": null,
"childrenIds": [
"5a97e047f826a0111b754beb"
]
}
]
What I'd like to do is a function that returns another array, but this time with only items that don't have a parentID as root elements, and have a children array on them containing their children, so on reaching leaves who have an empty childrenIDs array. (also remove the parent/children id properties)
For the previous input I'd return something like this
[
{
"id": "5c7bf2191d41c810b2ad6186",
"name": "Defense Against The Dark Arts",
"children": [
{
"id": "5a97e047f826a0111b754beb",
"name": "Hogwarts"
}
]
}
]
I can't seem to think of any efficient code for this task, can anyone help?
You could keep a reference to each node by ID in an object and build the tree while you go. Since we may encounter references to entries that we didn't see yet, we'll create stubs in the meantime (consisting only of a children array) and add the rest of their fields later on.
This way we have only a single loop.
It seems you have sort of a vertical double-linked list, saving both the parent ID in the children and the children's IDs in the parent, but we need only one of those to build the tree. We'll use the parent ID stored in each child. (Note that this assumes that your structure is consistent without imbalanced relations or dangling references.)
For simplicity, we create one root node whose children we'll return at the end, so that we don't have to handle the nodes without parent any differently.
Then you could write code like this:
function makeTree (rows) {
// Use a symbol to denote the root ID to avoid clashes with any real IDs
const ROOT = Symbol('ROOT')
// Node index, by ID
// Add a root node from the start
const nodes = { [ROOT]: { children: [] } }
// Helper function to return an existing node or create a stub if not existing
const getNodeOrCreateStub = id => nodes[id] || (nodes[id] = { children: [] })
for (const row of rows) {
// Add current row to index, merging data with existing stub, if any.
// This keeps any existing references in other nodes' children arrays intact
// because Object.assign mutates the first object passed to it and returns the
// same object.
const node = Object.assign(getNodeOrCreateStub(row.id), row)
// Remove unwanted properties.
delete node.parentId
delete node.childrenIds
// Get parent or create parent stub if parent node not already existing
const parent = getNodeOrCreateStub(row.parentId || ROOT)
// Add current node as child to parent
parent.children.push(node)
}
// Return children of root node
return nodes[ROOT].children
}
Note that this code currently also creates empty children arrays in the leaf nodes, differently from your example above. However I think this makes the code simpler because it doesn't have to handle leaf nodes any different, neither in creating the tree nor in reading it later! (You wouldn't have to do children && children.length to check for children, you could always just access children directly.)
To change that and have the result exactly as in your example, you'd change the code as follows:
// Change this...
const getNodeOrCreateStub = id => nodes[id] || (nodes[id] = { children: [] })
// ...to this:
const getNodeOrCreateStub = id => nodes[id] || (nodes[id] = {})
// Also change this...
parent.children.push(node)
// ...to this:
if (!parent.children) parent.children = []
parent.children.push(node)
// ...or to this:
parent.children = [...parent.children || [], node]

How to delete items of array based on object id list in mongoose?

I'm stuck with this and I thought you could help me somehow, from the frontend it arives me a list of numbers which contains the ids of the object to be removed, for instance :
{
"user":"TEST",
"conditionsToDelete":[1586513509594,1586513519698]
}
And my documents on mongo look like:
As you see there is a property named id on the document > conditionConfig > id
So this list which comes me from the front has this id's which I have to use in order to filter and delete the matching objects.
How I can do it? I've been trying something like the following:
let resBusqueda = await this.conditionModel.find({ user: conditionsPack.user });
resBusqueda.forEach(condicionPack => {
let condicionesFiltradas = [];
condicionPack.conditionConfig.forEach(condicion => {
let idAnalizadoActualSubcondicion = conditionsPack.conditionsToDelete.indexOf(condicion.id);
if (idAnalizadoActualSubcondicion == -1) {
condicionesFiltradas.push(condicion);
}
});
condicionPack.conditionConfig = condicionesFiltradas;
condicionesFiltradas = [];
});
I receive the Document and make some changes on it but how can I save them?
Ty in advance
there is a good example in here. but this might be good enough for you:
db.YourModel.update(
{ }, // conditions that specify your user instance
{ $pull: { firstArray: { $in: arrayOfObjectIds }, secondArray: "single ID" } },
{ multi: true }
)
I brought you example for single element removal and for your case, array of elements to be removed.

How to delete references to children of deleted properties

When I delete an object property, I need to remove all references to descendant properties scattered around my application:
const people = {
mary: {
children: [
john: new ChildClass(),
paul: new ChildClass(),
george: new ChildClass()
]
},
homer: {
children: [
bart: new ChildClass(),
lisa: new ChildClass(),
maggie: new ChildClass()
]
}
};
const all_children = [];
/* pseudocode:
foreach people(children) {
foreach children(child) {
all_children.push(child);
}
}
*/
all_children.forEach(child => {
/* does something with mary and homer's children */
});
//////////////////
delete people.mary;
all_children.forEach(child => {
/* STILL does something with mary and homer's children,
even though mary has been deleted */
});
So I either need a way to delete all references to descendant properties, or I need a way to indicate that the reference is tied to a deleted parent and ignore it in my calculations.
What is the proper/most maintainable way to accomplish this.
Unless you really need to keep all the children in one array for performance reasons, the easier solution is to scrap the all_children array in favor of a function that returns an array of all children, like
function getAllChildren () {
var all_children = [];
/* pseudocode:
foreach people(children) {
foreach children(child) {
all_children.push(child);
}
}
*/
return all_children;
}
This way, if you delete Mary or Homer, calling this function will automatically reflect the deletion.
If I understand the question correctly, you're afraid of the children objects still exist in memory after you remove parent object from the object array. This isn't the case for javascript, because the language doesn't implement true classes. And therefore each copy of the new ChildClass() is passed by value and not reference.
Therefore you don't need to keep track of the children references in order to clean them up.

can't get nested forEach to work in Javascript

So I guess the title is selfexplanatory. I have some code with nested forEach loops inside it. The loops are iterating over an array of chapter objects. Each object can have multiple child nodes and they again can have multiple child nodes, and so on.
I want to end up with one array which contains nested arrays with the child nodes.
So far my code looks like this:
exports.chapter = function(req, res) {
var chapters = [],
result = [];
chapters = exports.index(req, res);
chapters.forEach(function(chapter) {
if(chapter.orphan){
result.add({
'chapter': chapter,
'children': getChildren(chapter.children)
});
}
});
function getChildren(siblings) {
var children = [];
chapters.forEach(function(chapter) {
if($.inArray(chapter, siblings)){
children.add({
'chapter': chapter,
'children': getChildren(chapter.children)
});
}
});
return children;
};
};
I don't get any errors except for my page not loading. It doesn't write anything in my console. I think it's a problem in the setup but I'm unable to find out where at the moment. Really hope you guys can help.
Most likely problem is here:
if($.inArray(chapter, siblings)){
$.inArray is a horribly misnamed method: It returns an index, or -1 if not found, not a flag as the name implies. -1 is, of course, truthy; and 0 (a valid index), is falsey, so your if probably wants to be
if($.inArray(chapter, siblings) != -1){
// We found it...
}
or possibly
if($.inArray(chapter, siblings) == -1){
// We didn't find it
}
It's a bit strange.. I don't understand why you're using 'add' instead of 'push' method. If I try to "add" an object to an array I get an usual error. Don't you?

Categories