docs: function listents(seneca, entmap, qent, q, done) {
    var list = []
  
    var canon = qent.canon$({ object: true })
    var base = canon.base
    var name = canon.name
  
    var entset = entmap[base] ? entmap[base][name] : null
  
    if (entset) {
      if (_.isString(q)) {
        var ent = entset[q]
        if (ent) {
          list.push(ent)
        }
      }
      if (_.isArray(q)) {
        _.each(q, function(id) {
          var ent = entset[id]
          if (ent) {
            ent = qent.make$(ent)
            list.push(ent)
          }
        })
      }
      if (_.isObject(q)) {
        _.keys(entset).forEach(function(id) {
          var ent = entset[id]
          for (var p in q) {
            if (!~p.indexOf('$') && q[p] !== ent[p]) {
              return
            }
          }
          ent = qent.make$(ent)
          list.push(ent)
        })
      }
    }
  
    // Always sort first, this is the 'expected' behaviour.
    if (q.sort$) {
      for (var sf in q.sort$) {
        break
      }
  
      var sd = q.sort$[sf] < 0 ? -1 : 1
      list = list.sort(function(a, b) {
        return sd * (a[sf] < b[sf] ? -1 : a[sf] === b[sf] ? 0 : 1)
      })
    }
  
    // Skip before limiting.
    if (q.skip$ && q.skip$ > 0) {
      list = list.slice(q.skip$)
    }
  
    // Limited the possibly sorted and skipped list.
    if (q.limit$ && q.limit$ >= 0) {
      list = list.slice(0, q.limit$)
    }
  
    // Prune fields
    if (q.fields$) {
      for (var i = 0; i < list.length; i++) {
        var entfields = list[i].fields$()
        for (var j = 0; j < entfields.length; j++) {
          if ('id' !== entfields[j] && -1 == q.fields$.indexOf(entfields[j])) {
            delete list[i][entfields[j]]
          }
        }
      }
    }
  
    // Return the resulting list to the caller.
    done.call(seneca, null, list)
  }