Skip to content

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

Open
@spiritdead

Description

@spiritdead

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions