javascriptmongodbtreenested-sets

Nested set tree view data structure using with recursing and traversal techniques in MongoDB or JavaScript


Hey I'm trying to implement nested drag&drop within re-order sequencesin my MERN app. I working to find ideal approach for mongodb data model and implement to Lexicographic order or linked lists for infinite sub folders. I used Model Tree Structures in this link but every node have limitless children for that require recursion and recursive functions or currying. Documentations not clear enough for make do that.

I want show all tree once and not sohuld appear after than click to arrow icon.There is my doodles for front side generation that working with only one depth such like graph nodes. Maybe Modified Preorder Tree Traversal implementation examples you have for this scenario.


const tree = data => {  // immutable array
    let ascendants = data.filter(d=>d.parent==null)
    let descandants = data.filter(d=>d.parent)
  **strong text**
    let form = []
    ascendants.map(a=>{
        let node1 = {...a}; /// copying
            
            let node1Children = []; 
            descandants.map(b=>{
                let node2 = {...b};
                
                if(node1._id == b.parent){
                     node1Children.push(node2)
                }
                
            })

        node1.children = node1Children;


        form.push(node1);
    })
    return form;


}

I cant take result with using $graphLookup because list format is not what i want.Could you give me some mongodb playground or grouping aggregate solutions? Below json examples shown my expecting results. I can do before but hardcode is unapropriate and performless. Is comparing good way?



[
    // mongo database
    {_id:123, title:'Books', slug:'books', parent:null },
    {_id:124, title:'Programming', slug:'programming', parent:null },
    {_id:125, title:'JavaScript', slug:'javascript', parent:'programming' },
    {_id:126, title:'C++',slug:'cpp', parent:'programming' },
    {_id:127, title:'React', slug:'react', parent:'javascript' },
    {_id:128, title:'Redux', slug:'redux', parent:'react' },
    {_id:129, title:'Toolkit', parent:'redux' },
    {_id:130, title:'Saga', parent:'redux' },
    {_id:131, title:'Nodejs', parent:'programming' },
    {_id:132, title:'Databases', slug:'databases' },
    {_id:133, title:'MongoDB', parent:'databases' },
]

[
   // what i want
   { title: "Books"},
   { title: "Programming", parent:"computer-science", children: [

        { title: "JavaScript", children: [
            { title: "React",  children: [
                { title: "Redux", children: [
                    { title: "Saga" },
                    { title: "Thunk" },
                    { title: "Mobx" },
                    { title: "Observable" },
                    { title: "Context" },
                    { title: "GraphQL" },
                    { title: "Toolkit", children:[
                        { title: "typescript" },
                        { title: "slices", children:[
                            { title: "createAsyncThunk" },
                            { title: "createSlice" },
                        ] },
                   ] },

                ] },
                { title: "Nextjs" },
            ]},
            { title: "Vue", },
            { title: "angular", },

        ]},
        { title: "C++", },
        { title: "NodeJS", },

   ] },
   { title: "MongoDB", parent: "databases"},
] 

    


Solution

  • You could create a Map to key your objects by slug. The values per key will be the result objects for parent objects. Include an entry for null, which will collect the top-level elements.

    Then iterate the data again to populate children arrays -- when that property does not exist yet, create it on the fly. Finally output the top-level elements.

    function makeTree(data) {
        let children = []; // Top-level elements
        let map = new Map(data.map(({title, slug}) => [slug, { title }]))
                         .set(null, {children});
        for (let {slug, parent, title} of data) {
            (map.get(parent || null).children ??= [])
                    .push(slug ? map.get(slug) : {title});
        }
        return children;
    }
    
    // Your mongodb data:
    const data = [{_id:123, title:'Books', slug:'books', parent:null },{_id:124, title:'Programming', slug:'programming', parent:null },{_id:125, title:'JavaScript', slug:'javascript', parent:'programming' },{_id:126, title:'C++',slug:'cpp', parent:'programming' },{_id:127, title:'React', slug:'react', parent:'javascript' },{_id:128, title:'Redux', slug:'redux', parent:'react' },{_id:129, title:'Toolkit', parent:'redux' },{_id:130, title:'Saga', parent:'redux' },{_id:131, title:'Nodejs', parent:'programming' },{_id:132, title:'Databases', slug:'databases' },{_id:133, title:'MongoDB', parent:'databases' }];
    
    console.log(makeTree(data));