title: MongoDB Tree Model: Get all ancestors, Get all descendants
body: <p>I have an arbitrary tree structure. </p>
  
  <h2>Example data structure:</h2>
  
  <pre><code>root
    |--node1
    |     |--node2
    |     |     |--leaf1
    |     |
    |     |--leaf2
    |
    |--node3
          |--leaf3
  </code></pre>
  
  <p>Each node and leaf has 2 properties: <code>id</code> and <code>name</code>.</p>
  
  <hr>
  
  <h2>The important queries:</h2>
  
  <p><code>1.:</code> A leaf id is given. The query should return the whole path from root to that leaf, with all node's <code>id</code> and <code>name</code> properties.</p>
  
  <p>It's not important if the return value is an sorted array of nodes or if it's an object where the nodes are nested.</p>
  
  <p><strong>Example:</strong> If the <code>id</code> of <code>leaf2</code> is given, the query should return: <code>root(id, name), node1(id, name), leaf2(id, name)</code>.</p>
  
  <hr>
  
  <p><code>2.:</code> Given any node <code>id</code>: Get the whole (sub)tree. Here it would be nice to retrieve a single object where each node has a <code>children</code> array.</p>
  
  <hr>
  
  <h2>Thoughts, trials and errors:</h2>
  
  <p><code>1.:</code> First I tried to simply model the tree as a single JSON document, but then the query would become impossible: There's no way to find out at which nesting level the leaf is. And if I knew the whole path of <code>id</code>s from root to the leaf, I'd had to use a projection with multiple positional operators and that's not supported by MongoDB at the moment. Additionally it's not possible to index the leaf <code>ids</code> because the nesting can be infinite.</p>
  
  <p><code>2.:</code> Next idea was to use a flat data design, where each node has an array which contains the node's ancestor <code>ids</code>:</p>
  
  <pre><code>{
    id: ...,
    name: ...,
    ancestors: [ rootId, node1Id, ... ]
  }
  </code></pre>
  
  <p>This way I'd have to do 2 queries, to get the whole path from root to some node or leaf, which is quite nice.</p>
  
  <h2>Questions:</h2>
  
  <p>If I choose data model <code>2.</code>: How can I get the whole tree, or a subtree?</p>
  
  <p>Getting all descendants is easy: <code>find({ancestors:"myStartingNodeId"})</code>. But those will of course be not sorted or nested.</p>
  
  <p>Is there a way using the aggregation framework or a completely different data model to solve this problem?</p>
  
  <p>Thank you!</p>