code: function read(model) {
    var query = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
    var mode = arguments.length <= 2 || arguments[2] === undefined ? 'read' : arguments[2];
  
    return _columns2['default'](model).then(function (modelColumns) {
      var fields = query.fields && query.fields[_type2['default'](model)];
      var relations = _lodash2['default'].intersection(_all_relations2['default'](model), query.include || []);
      if (fields) {
        fields = _lodash2['default'].intersection(modelColumns, fields);
        // ensure we always select id as the spec requires this to be present
        if (!_lodash2['default'].contains(fields, 'id')) {
          fields.push('id');
        }
      }
      return model.collection().query(function (qb) {
        qb = processFilter(model, qb, query.filter);
        qb = processSort(model.columns, qb, query.sort);
      }).fetch({
        // adding this in the queryBuilder changes the qb, but fetch still
        // returns all columns
        columns: fields,
        withRelated: relations
      }).then(function (result) {
        // This is a lot of gross in order to pass this data into the
        // formatter later. Need to formalize this in some other way.
        result.mode = mode;
        result.relations = relations;
        result.singleResult = query.singleResult;
        result.baseType = query.baseType;
        result.baseId = query.baseId;
        result.baseRelation = query.baseRelation;
        return result;
      });
    });
  }
docs: Retrieves a collection of models from the database.
  
  @param {Bookshelf.Model} model - a bookshelf model class
  @param {Object} query - the output of Request#query
  @param {Object} mode - the mode of the request (single/related/relation)
  @return {Promise.Bookshelf.Collection} Models that match the request.