Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build javascript tree based on parent attribute in array of elements

I'm trying to store a directory tree in a mongoDB. Here's my schema:

{ "_id" : ObjectId("541ba7f156d876d3f787bc33"), "name" : "file_1.mp3", "length" : 136.6, "kind" : "audio", "parent" : null }
{ "_id" : ObjectId("541ba7f156d876d3f787bc34"), "name" : "file_2.mp3", "length" : 132.0, "kind" : "audio", "parent" : null }
{ "_id" : ObjectId("541ba7f156d876d3f787bc35"), "name" : "file_3.mp3", "length" : 116.8, "kind" : "audio", "parent" : null }
{ "_id" : ObjectId("541ba7f156d876d3f787bc36"), "name" : "file_4.mp3", "length" : 206.7, "kind" : "audio", "parent" : null }
{ "_id" : ObjectId("541ba84456d876d3f787bc37"), "name" : "folder_1", "length" : null, "kind" : "dir", "parent" : null }
{ "_id" : ObjectId("541ba84456d876d3f787bc38"), "name" : "folder_2", "length" : null, "kind" : "dir", "parent" : null }
{ "_id" : ObjectId("541ba84456d876d3f787bc39"), "name" : "folder_3", "length" : null, "kind" : "dir", "parent" : null }
{ "_id" : ObjectId("541ba91656d876d3f787bc3a"), "name" : "subfolder_1", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba84456d876d3f787bc37") }
{ "_id" : ObjectId("541ba91656d876d3f787bc3b"), "name" : "subfolder_2", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba84456d876d3f787bc37") }
{ "_id" : ObjectId("541ba91656d876d3f787bc3c"), "name" : "subfolder_3", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba84456d876d3f787bc37") }
{ "_id" : ObjectId("541ba98056d876d3f787bc3d"), "name" : "subsubfolder_1", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba91656d876d3f787bc3b") }
{ "_id" : ObjectId("541ba98056d876d3f787bc3e"), "name" : "subsubfolder_2", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba91656d876d3f787bc3b") }
{ "_id" : ObjectId("541ba98056d876d3f787bc3f"), "name" : "subsubfolder_3", "length" : null, "kind" : "dir", "parent" : ObjectId("541ba91656d876d3f787bc3b") }

I want to changes this so that the children get nested inside the parents. i.e.:

[
  { 
    "_id" : ObjectId("541ba7f156d876d3f787bc33"),
    "name" : "file_1.mp3",
    "length" : 136.6,
    "kind" : "audio",
    "parent" : null
  }
  { 
    "_id" : ObjectId("541ba7f156d876d3f787bc34"),
    "name" : "file_2.mp3",
    "length" : 136.6,
    "kind" : "audio",
    "parent" : null
  }
  {
    "_id" : ObjectId("541ba7f156d876d3f787bc35"),
    "name" : "file_3.mp3",
    "length" : 136.6,
    "kind" : "audio",
    "parent" : null
  }
  {
    "_id" : ObjectId("541ba7f156d876d3f787bc36"),
    "name" : "file_4.mp3",
    "length" : 136.6,
    "kind" : "audio",
    "parent" : null
  }
  {
    "_id" : ObjectId("541ba84456d876d3f787bc37"),
    "name" : "folder_1",
    "length" : null,
    "kind" : "dir",
    "parent" : null
    "children": [
      {
        "_id" : ObjectId("541ba91656d876d3f787bc3a"),
        "name" : "subfolder_1",
        "length" : null,
        "kind" : "dir",
        "parent" : ObjectId("541ba84456d876d3f787bc37")
      },
      {
        "_id" : ObjectId("541ba91656d876d3f787bc3b"),
        "name" : "subfolder_2",
        "length" : null,
        "kind" : "dir",
        "parent" : ObjectId("541ba84456d876d3f787bc37")
        "children": [
          {
            "_id" : ObjectId("54198056d876d3f787bc3d"),
            "name" : "subsubfolder_1",
            "length" : null,
            "kind" : "dir",
            "parent" : ObjectId("541ba91656d876d3f787bc3b")
          }
          {
            "_id" : ObjectId("541ba98056d876d3f787bc3e"),
            "name" : "subsubfolder_2",
            "length" : null,
            "kind" : "dir",
            "parent" : ObjectId("541ba91656d876d3f787bc3b")
          }
          {
            "_id" : ObjectId("541ba98056d876d3f787bc3f"),
            "name" : "subsubfolder_3",
            "length" : null,
            "kind" : "dir",
            "parent" : ObjectId("541ba91656d876d3f787bc3b")
          }
        ]
      },
      {
        "_id" : ObjectId("541ba91656d876d3f787bc3c"),
        "name" : "subfolder_3",
        "length" : null,
        "kind" : "dir",
        "parent" : ObjectId("541ba84456d876d3f787bc37")
      }
    ]
  }
  {
    "_id" : ObjectId("541ba84456d876d3f787bc38"),
    "name" : "folder_2",
    "length" : null,
    "kind" : "dir",
    "parent" : null
  }
  {
    "_id" : ObjectId("541ba84456d876d3f787bc39"),
    "name" : "folder_3",
    "length" : null,
    "kind" : "dir",
    "parent" : null
  }

Here's the function I'm using to try to accomplish this:

getChildren = function(element) {
  // find all the entries that have this element as their parent
  var results = FileTree.find({'parent': element._id});

  // did we find any children?
  if (results.count() !== 0) {
    // get an array from the mongo cursor
    var rArr = results.fetch();
    // attach a '.children' object to each of the children
    // so that we continue the tree
    var children = _.each(rArr, getChildren);
    //make this subtree part of the original element
    element.children = children;
    return element;
  }
  else { // the element doesn't have any children
     element.children = null;
     return element;
  }
};

I call the function like this:

id = new Meteor.Collection.ObjectID("541ba84456d876d3f787bc37");
getChildren(FileTree.findOne({'_id': id}));

My console returns this:

Object { _id: Object, name: "folder_1", length: null, kind: "dir", parent: null, children: undefined }

Why is children undefined?

Here's a live demo: http://meteorpad.com/pad/imyw4w7z7dihss9t3

like image 576
BonsaiOak Avatar asked Sep 19 '14 16:09

BonsaiOak


1 Answers

You want to use _.map instead of _.each, see here.

_.map returns the array with results of your iteration function, which is what you want to assign to the children param. _.each just loops trough your collection, returning undefined.

like image 114
Hubert OG Avatar answered Oct 20 '22 00:10

Hubert OG