title: How to find parents based on child fields in mongo using aggregation?
body: <p>Here is a code I have:</p>
  
  <pre><code>const _ = require('lodash')
  const Box = require('./models/Box')
  
  const boxesToBePicked = await Box.find({ status: 'ready', client: 27 })
  const boxesOriginalIds = _(boxesToBePicked).map('original').compact().uniq().value()
  const boxesOriginal = boxesOriginalIds.length ? await Box.find({ _id: { $in: boxesOriginalIds } }) : []
  
  const attributes = ['name']
  
  const boxes = [
    ...boxesOriginal,
    ...boxesToBePicked.filter(box =&gt; !box.original)
  ].map(box =&gt; _.pick(box, attributes))
  </code></pre>
  
  <p>Let's say, we have following data in "boxes" collection:</p>
  
  <pre><code>[
    { _id: 1, name: 'Original Box #1', status: 'pending' },
    { _id: 2, name: 'Nested box', status: 'ready', original: 1 },
    { _id: 3, name: 'Nested box', status: 'ready', original: 1 },
    { _id: 4, name: 'Nested box', status: 'pending', original: 1 },
    { _id: 5, name: 'Original Box #2', status: 'ready' },
    { _id: 6, name: 'Original Box #3', status: 'pending' },
    { _id: 7, name: 'Nested box', status: 'ready', original: 6 },
    { _id: 8, name: 'Original Box #4', status: 'pending' }
  ]
  </code></pre>
  
  <p>Workflow</p>
  
  <p>Find all boxes, which are ready to be picked:</p>
  
  <pre><code>const boxesToBePicked = await Box.find({ status: 'ready' })
  
  // Returns:
  
  [
    { _id: 2, name: 'Nested box', status: 'ready', original: 1 },
    { _id: 3, name: 'Nested box', status: 'ready', original: 1 },
    { _id: 5, name: 'Original Box #2', status: 'ready' },
    { _id: 7, name: 'Nested box', status: 'ready', original: 6 }
  ]
  </code></pre>
  
  <p>Get all the IDs of original (parent) boxes of those:</p>
  
  <pre><code>const boxesOriginalIds = _(boxesToBePicked).map('original').compact().uniq().value()
  
  // Returns:
  
  [1, 6]
  </code></pre>
  
  <p>Get those boxes by their IDs:</p>
  
  <pre><code>const boxesOriginal = boxesOriginalIds.length ? await Box.find({ _id: { $in: boxesOriginalIds } }) : []
  
  // Returns
  
  [
    { _id: 1, name: 'Original Box #1', status: 'pending' },
    { _id: 6, name: 'Original Box #3', status: 'pending' }
  ]
  </code></pre>
  
  <p>Join those boxes with not nested boxes to be picked:</p>
  
  <pre><code>const boxes = [
    ...boxesOriginal,
    ...boxesToBePicked.filter(box =&gt; !box.original)
  ].map(box =&gt; _.pick(box, attributes))
  
  // Returns
  
  [
    { name: 'Original Box #1' },
    { name: 'Original Box #3' },
    { name: 'Original Box #2' }
  ]
  </code></pre>
  
  <p>So basically what we are doing here is getting all the original boxes if they have at least one nested box with status "ready", and all not nested boxes with status "ready".</p>
  
  <p>I think it can be simplified by using aggregation pipeline and projection. But how?</p>