protected function getData() {

        $sql = ['SELECT document FROM '.$this->collection->name];

        if ($this->criteria) {

            $sql[] = 'WHERE document_criteria("'.$this->criteria.'", document)';
        }

        if ($this->sort) {

            $orders = [];

            foreach ($this->sort as $field => $direction) {
                $orders[] = 'document_key("'.$field.'", document) '.($direction==-1 ? 'DESC':'ASC');
            }

            $sql[] = 'ORDER BY '.\implode(',', $orders);
        }

        if ($this->limit) {
            $sql[] = 'LIMIT '.$this->limit;

            if ($this->skip) { $sql[] = 'OFFSET '.$this->skip; }
        }

        $sql = implode(' ', $sql);

        $stmt      = $this->collection->database->connection->query($sql);
        $result    = $stmt->fetchAll( \PDO::FETCH_ASSOC);
        $documents = [];

        if (!$this->projection) {

            foreach ($result as &$doc) {
                $documents[] = \json_decode($doc['document'], true);
            }

        } else {

            $exclude = [];
            $include = [];

            foreach ($this->projection as $key => $value) {

                if ($value) {
                    $include[$key] = 1;
                } else {
                    $exclude[$key] = 1;
                }
            }

            foreach ($result as &$doc) {

                $item = \json_decode($doc['document'], true);
                $id   = $item['_id'];

                if ($exclude) {
                    $item = \array_diff_key($item, $exclude);
                }

                if ($include) {
                    $item = array_key_intersect($item, $include);
                }

                if (!isset($exclude['_id'])) {
                    $item['_id'] = $id;
                }

                $documents[] = $item;
            }
        }

        return $documents;
    }