yiisoft / yii2-mongodb

Yii 2 MongoDB extension
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
326 stars 191 forks source link

Out of memory using Model::find()->one() #303

Open spiritdead opened 4 years ago

spiritdead commented 4 years ago

What steps will reproduce the problem?

Create a collection with 500k records try to use $model = Model::find()->one();

What's expected?

get the model

What do you get instead?

Fatal error Out of memory

Additional info

Reading Query.php i found that when we enter in this method

protected function fetchRowsInternal($cursor, $all)
    {
        $result = [];
        if ($all) {
            foreach ($cursor as $row) {
                $result[] = $row;
            }
        } else {
            if ($row = current($cursor->toArray())) {
                $result = $row;
            } else {
                $result = false;
            }
        }

        return $result;
    }

in this moment $cursor is not limited with (limit = 1) and the cursor try to fetch the full collection generating an out of memory

Proposal Solution is add limit = 1 when we try to get one

public function one($db = null)
    {
        if (!empty($this->emulateExecution)) {
            return false;
        }
        $cursor = $this->buildCursor($db);
        return $this->fetchRows($cursor, false);
    }

after the change should looks like this

public function one($db = null)
    {
        if (!empty($this->emulateExecution)) {
            return false;
        }

        if (!isset($this->limit)) {
            $this->limit = 1;
        }

        $cursor = $this->buildCursor($db);
        return $this->fetchRows($cursor, false);
    }
Q A
Yii version
Yii MongoDB version
MongoDB server version
PHP version
Operating system
samdark commented 4 years ago

Related to https://github.com/yiisoft/yii2-mongodb/issues/290