public function getTableRows(
        $tableSpecId,
        array $filter = [],
        array $sortBy = [],
        $offset = 0,
        $limit = 10,
        array $options = []
    ) {
        $t = new \Tripod\Timer();
        $t->start();

        $options = array_merge(
            [
                'returnCursor' => false,
                'includeCount' => true,
                'documentType' => '\Tripod\Mongo\Documents\Tables'
            ],
            $options
        );

        $filter['_id.' . _ID_TYPE] = $tableSpecId;

        $collection = $this->getConfigInstance()->getCollectionForTable(
            $this->storeName,
            $tableSpecId,
            $this->readPreference
        );

        $findOptions = [];
        if (!empty($limit)) {
            $findOptions['skip'] = (int) $offset;
            $findOptions['limit'] = (int) $limit;
        }
        if (isset($sortBy)) {
            $findOptions['sort'] = $sortBy;
        }

        $results = $collection->find($filter, $findOptions);

        if ($options['includeCount']) {
            $count = $collection->count($filter);
        } else {
            $count = -1;
        }


        $results->setTypeMap(['root' => $options['documentType'], 'document' => 'array', 'array' => 'array']);

        $t->stop();
        $this->timingLog(
            MONGO_TABLE_ROWS,
            ['duration' => $t->result(), 'query' => $filter, 'collection' => TABLE_ROWS_COLLECTION]
        );
        $this->getStat()->timer(MONGO_TABLE_ROWS . ".$tableSpecId", $t->result());

        return [
            'head' => [
                'count' => $count,
                'offset' => $offset,
                'limit' => $limit
            ],
            'results' => $options['returnCursor'] ? $results : $results->toArray()
        ];
    }