Magento: Lọc bộ sưu tập đơn đặt hàng lớn


7

Tôi đang cố gắng để lọc một bộ sưu tập lớn của đơn đặt hàng. Có hơn 5 triệu hồ sơ trong đó. Dưới đây là mã của tôi để có được bộ sưu tập đơn hàng và tôi cũng đặt một số phép nối để có được các cột mong muốn

    $resource = Mage::getSingleton('core/resource');
    $collection = Mage::getResourceModel('sales/order_grid_collection');

    $collection ->join(
      'sales/order_item',
    '`sales/order_item`.order_id=`main_table`.entity_id',
    array(
    'skus' => new Zend_Db_Expr('GROUP_CONCAT(`sales/order_item`.sku SEPARATOR "</br>")'),
    )
    );



    $collection->getSelect()->joinLeft(array('sfog' => $resource->getTableName('sales_flat_order_grid')),
    'main_table.entity_id = sfog.entity_id',array('sfog.shipping_name','sfog.billing_name'));

    $collection->getSelect()->joinLeft(array('sfo'=>  $resource->getTableName('sales_flat_order')),
    'sfo.entity_id=main_table.entity_id',array('sfo.customer_email','sfo.weight',
    'sfo.discount_description','sfo.increment_id','sfo.store_id','sfo.created_at','sfo.status',
    'sfo.base_grand_total','sfo.grand_total'));

    $collection->getSelect()->joinLeft(array('sfoa'=>  $resource->getTableName('sales_flat_order_address')),
    'main_table.entity_id = sfoa.parent_id AND sfoa.address_type="shipping"',array('sfoa.street',
    'sfoa.city','sfoa.region','sfoa.postcode','sfoa.telephone','sfoa.fax'));

Khi tôi áp dụng addAttributeToFilterchức năng trên bộ sưu tập này thì phải mất 10 phút để lấy kết quả. Câu hỏi của tôi là có cách nào hiệu quả và nhanh chóng để lọc bộ sưu tập

Cập nhật

Dưới đây là bộ lọc logic của tôi. Tôi muốn tìm kiếm một đơn đặt hàng bằng cách sử dụng các bộ lọc khác nhau

    $email = Mage::app()->getRequest()->getParam('email');

    $phone = Mage::app()->getRequest()->getParam('phone');

    $postcode = Mage::app()->getRequest()->getParam('postcode');

    $skus = Mage::app()->getRequest()->getParam('skus');

    if($email!='')
    {
        $collection->addAttributeToFilter('sfo.customer_email',$email);
    }

    if($phone!='' && $postcode=='')
    {
        $phone = str_replace(' ', '', $phone); // Replaces all spaces with hyphens.
        $phone = preg_replace('/[^A-Za-z0-9\-]/', '', $phone); // Removes special chars.
        $collection->addAttributeToSearchFilter(
            array(
                array(
                    'attribute' => 'sfoa.telephone',
                    'eq' => $phone
                ),
                array(
                    'attribute' => 'sfoa.fax',
                    'eq' => $phone
                )
            )
        );
    }

    if($postcode!='' && $phone!='')
    {
        $collection->addAttributeToFilter('sfoa.postcode',$postcode);
        $phone = str_replace(' ', '', $phone); // Replaces all spaces with hyphens.
        $phone = preg_replace('/[^A-Za-z0-9\-]/', '', $phone); // Removes special chars.
        $collection->addAttributeToFilter('sfoa.telephone',$phone);
    }

    if($skus!='')
    {
        $sku_array = explode(",",$skus);
        $collection->addAttributeToFilter('sku', array('in' => array('finset' => array($sku_array))));
    }

Câu trả lời:


2

Khi bạn làm việc với các bộ sưu tập rất lớn, sẽ có rất nhiều khả năng bạn sẽ gặp phải một lỗi nghiêm trọng Kích thước bộ nhớ cho phép của các byte X hết hoặc hết thời gian . Trong trường hợp của bạn, nó không xảy ra nhưng nó mất rất nhiều thời gian.

May mắn thay, mặc dù hầu hết mọi người không biết về nó, Magento cung cấp một giải pháp cho điều đó, Mage_Core_Model_Resource_Iteratormô hình. Về cơ bản, nó cho phép bạn lấy dữ liệu từ cơ sở dữ liệu thông qua một trình vòng lặp (vì vậy từng cái một) thay vì tải mọi kết quả cùng một lúc như bạn làm trong mã của mình.

Trình lặp đang sử dụng walk()phương thức yêu cầu hai tham số: chuỗi truy vấn cơ sở dữ liệu bộ sưu tậpphương thức gọi lại .

Các walk()phương pháp mã trông như thế này:

public function walk($query, array $callbacks, array $args=array(), $adapter = null)
{
    $stmt = $this->_getStatement($query, $adapter);
    $args['idx'] = 0;
    while ($row = $stmt->fetch()) {
        $args['row'] = $row;
        foreach ($callbacks as $callback) {
            $result = call_user_func($callback, $args);
            if (!empty($result)) {
                $args = array_merge($args, $result);
            }
        }
        $args['idx']++;
    }

    return $this;
}

Bạn không nói chính xác mã của bạn đang làm gì (nếu bạn lặp qua các kết quả hoặc nếu bạn muốn xuất nó), vì vậy tôi sẽ chỉ cho bạn một ví dụ mà bạn có thể sử dụng.

Sau khi mã bạn dán, bạn có thể làm như sau:

Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array(array($this, 'collectionCallback')));

Trong cùng một lớp, bạn cần tạo collectionCallbackphương thức:

public function collectionCallback($args)
{
    // The data for each entry is stored here
    $data = $args['row'];
    // Do something with the data
}

Tôi không biết hiệu suất của nó sẽ tốt như thế nào so với addAttributeToFilterphương thức nhưng bạn có thể thực hiện bộ lọc trực tiếp bằng cách sử dụng chức năng gọi lại này, ví dụ:

public function collectionCallback($args)
{
    // The data for each entry is stored here
    $data = $args['row'];
    if ($data['attribute'] != "test") {
        return;
    }

}

tôi muốn tìm kiếm các đơn đặt hàng bằng các bộ lọc khác nhau
Shaheer Ali

@ShaheerAli thật tuyệt, walkphương pháp này chính xác là những gì bạn cần
Raphael tại Digital Pianism

@Raphel kiểm tra câu hỏi cập nhật của tôi. Làm thế nào tôi có thể nhận được kết quả tương tự bằng cách sử dụng chức năng đi bộ
Shaheer Ali

@Raphel tại Kỹ thuật số. tôi đã thử giải pháp của bạn nhưng nó mất cùng thời gian và cũng không cho tôi kết quả :(
Shaheer Ali

0

Cách nhanh nhất và hiệu quả nhất để xử lý kích thước dữ liệu cuối cùng là sử dụng truy vấn SQL của tôi trong Magento để lấy dữ liệu cột mong muốn.

$resource = Mage::getSingleton('core/resource');

Để chạy một lựa chọn, bạn có thể làm một cái gì đó như thế này:

$readConnection = $resource->getConnection('core_read');

$query = 'SELECT * FROM ' . $resource->getTableName('custom/model');

$results = $readConnection->fetchAll($query);

1
Sử dụng fetchAllchắc chắn không phải là cách nhanh nhất và hiệu quả nhất
Raphael tại Digital Pianism
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.