ความแตกต่างระหว่าง getSize () และ count () ในการรวบรวม


81

ฉันเคยได้ยินหลายครั้งว่าพวกเขาทั้งสองเหมือนกัน แต่ฉันกำลังเผชิญกับปัญหาแปลก ๆ ในโมดูลผลิตภัณฑ์ CatalogSearch จำนวน () กำลังคืนจำนวนผลิตภัณฑ์ที่ถูกต้องขณะที่ getSize () กลับมาเป็นศูนย์

ดังนั้นโดยทั่วไปนี่คือสิ่งที่ฉันได้รับ:

$collection->count(); //correct count
$collection->getSize(); //0

แต่ฉันต้องการให้ getSize () มีจำนวนที่ถูกต้องตามที่ตัดสินใจว่าจะแสดงเลขหน้าและผลิตภัณฑ์ในหน้าค้นหาหรือไม่ ฉันกำลังใช้ Inner Join, Left Join และ Where มีเงื่อนไขเฉพาะในคอลเล็กชันเพื่อให้มีความเฉพาะเจาะจงมากขึ้น

ความคิดใดที่ว่าทำไมฉันถึงได้รับเรื่องแปลก ๆ นี้?

ขอบคุณ

UPDATE:

คำถามก่อนหน้าของฉันจะคัดลอกคอลเล็กชันใน Magento ได้อย่างไร ฉันต้องการดำเนินการสองอย่างที่แตกต่างกันในคอลเล็กชันเดียว คอลเล็กชันแรกแสดง getSize () ที่ถูกต้อง แต่ถ้า getSize () เป็นศูนย์ฉันจะลบส่วนคำสั่ง WHERE และให้เงื่อนไข WHERE ใหม่ หลังจากนี้ฉันได้รับ SQL ดิบที่ถูกต้องตามที่คาดไว้และการใช้งานใน MySQL จะให้ชุดของเรกคอร์ดที่ถูกต้อง แต่เพียง getSize () ในคอลเลกชันที่ให้จำนวนนับเป็นศูนย์

ดังนั้นโดยทั่วไปฉันอาจต้องโหลดคอลเลกชันใหม่เนื่องจาก getSize () กำลังนับจำนวนมาก มีเหตุผล?

คำตอบ:


83

มากที่สุด (ถ้าไม่ทั้งหมด) Varien_Data_Collection_Dbคอลเลกชันขยาย นี่คือ 2 วิธีจากคลาสนี้

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
} 

public function count() //inherited from Varien_Data_Collection
{
    $this->load();
    return count($this->_items);
}

มีความแตกต่าง สำหรับgetSize()คอลเลกชันไม่ได้โหลด สำหรับcount()มันคือ โดยปกติรุ่นคอลเลกชันใช้เดียวกันวิธีการดังกล่าวข้างต้นและมีเพียงการแทนที่getSize() ในขีด จำกัด จะถูกรีเซ็ตเพื่อให้ได้จำนวนทั้งหมดของระเบียนที่มีอยู่สำหรับตัวกรองชุด ( คำสั่ง) ดูวิธีการทำงานgetSelectCountSql()
getSelectCountSql()wheregetSelectCountSql()

public function getSelectCountSql()
{
    $this->_renderFilters();
    $countSelect = clone $this->getSelect();
    $countSelect->reset(Zend_Db_Select::ORDER);
    $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
    $countSelect->reset(Zend_Db_Select::COLUMNS);
    $countSelect->columns('COUNT(*)');
    return $countSelect;
} 

3
ที่ดี! ดังนั้นขั้นตอนต่อไปของฉันคือการโหลดคอลเลกชันใหม่เพื่อให้ถูกต้องgetSize()? ขอบคุณ!
MagExt

ฉันไม่รู้จริงๆว่าทำไมคุณถึงได้ผลลัพธ์นี้ ในCatalogSearchโมดูลมีอะไรที่จะแทนที่หรือgetSize() getSelectCountSql()มันควรจะทำงานโดยค่าเริ่มต้นเว้นแต่คุณจะเพิ่มรหัสที่กำหนดเองบางส่วน คุณช่วยโพสต์วิธีสร้างคอลเลกชันได้ไหม?
Marius

อัปเดตคำถาม
MagExt

3
_totalRecordsไม่มีทางที่จะตั้งค่าไม่เป็น คุณสามารถลองโคลนชุดก่อนที่จะโทรgetSize()ในชุดเดิม บางทีนั่นอาจจะใช้ได้
Marius

คุณสามารถทำสิ่งนี้เพื่อรับจำนวน "รีเซ็ต":$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
koosa

14

ระวัง. สิ่งนี้ถูกต้อง แต่วิธีการเขียนทับในVarien_Data_Collection_Dbตามที่อธิบายโดย Marius

เพียงแค่ดูได้

// \Varien_Data_Collection::getSize
public function getSize()
{
    $this->load();
    if (is_null($this->_totalRecords)) {
        $this->_totalRecords = count($this->getItems());
    }
    return intval($this->_totalRecords);
}

// \Varien_Data_Collection::count
public function count()
{
    $this->load();
    return count($this->_items);
}

ดังนั้นในระดับต่ำนี้ควรเหมือนกัน ทั้งสองวิธีโหลดคอลเลกชันและนับจำนวนรายการ

UPDATE

โอ้ฉันเห็นปัญหา: getSize () แคช _totalRecords นี่หมายความว่ามันไม่ได้คำนวณใหม่ ตรวจสอบว่า_totalRecordsตั้งอยู่ที่ไหน?


ใช่ฉันได้ดูแล้ว แต่ไม่สามารถเข้าใจได้ว่าทำไมทั้งสองจึงสร้างการนับที่แตกต่างกันสำหรับคอลเลกชันเดียวกัน ความคิดใดวิธีการโหลดเก็บรวบรวมหรือสิ่งที่จะได้รับการนับที่ถูกต้องในgetSize()?
MagExt

อัปเดตรายการ
Fabian Blechschmidt

1
getSize()ไม่โหลดคอลเลกชันสำหรับระเบียนที่มาจากฐานข้อมูล ไม่ใช่ยกเว้นว่าคุณจะแทนที่วิธีการและบอกให้โหลดคอลเลกชัน
Marius

_totalRecords ได้รับการคุ้มครองดังนั้นจึงไม่สามารถเรียกมันในไฟล์ที่กำหนดเองพร้อมคอลเลกชัน echo count($collection->load()->getItems());ให้นับถูกต้อง แต่ฉันต้องการgetSize()ทำงานอีกครั้ง
MagExt

5

คำตอบนี้แสดงใน google สำหรับ "magento getSize ผิด" และการค้นหาที่คล้ายกันดังนั้นฉันต้องการเพิ่มสถานการณ์ที่เป็นไปได้ที่อาจเป็นประโยชน์กับใครบางคน

เมื่อคุณมีคำสั่งกลุ่มในแบบสอบถามของคุณและคุณทำ

SELECT COUNT(DISTINCT e.entity_id) ... GROUP BY ( at_id_art.value )

Mysql จะส่งคืนการนับสำหรับแต่ละกลุ่มดังนั้น Varien_Data_Collection_Db :: getSize () จะส่งคืนคำตอบที่ไม่ถูกต้องนี่เป็นเพราะฟังก์ชั่นนี้ดึงแถวแรก:

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
}

เมื่อมันเติม

$this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);

มันเลือกแถวแรกและส่งกลับผลรวมของกลุ่มแรกเป็นขนาดรวม

ฉันลงเอยด้วยการใช้รหัสนี้เพื่อนับตามค่าที่ไม่ซ้ำกันของแอตทริบิวต์ในแบบสอบถามของฉัน

$select = clone $collection->getSelect();
$group = $select->getPart(Zend_Db_Select::GROUP);
$select->reset(Zend_Db_Select::GROUP)->reset(Zend_Db_Select::COLUMNS)->columns("COUNT(DISTINCT {$group[0]})");
$totalCount = $collection->getConnection()->fetchOne($select);

2

ในกรณีที่คุณลงเอยที่นี่มีวิธีแก้ไขง่ายๆให้ลอง:

System -> Index Management

และเลือกพวกเขาทั้งหมด (แม้ว่าพวกเขาจะระบุว่า "สีเขียวไม่จำเป็นต้องมีดัชนีใหม่" และบังคับให้พวกเขาทำดัชนีใหม่

นี่เป็นการแก้ไขปัญหาที่ว่างเปล่าของฉันgetSize()ซึ่งในทางกลับกันอนุญาตให้ฐานข้อมูลพิเศษและใหม่ร้องขอให้ค้นหาผลิตภัณฑ์ตอบสนองเงื่อนไข "ถ้า" และแสดงอย่างถูกต้อง


0

เมื่อcount($collection)แตกต่างจากที่$collection->getSize()ฉันมีกับreindexผลิตภัณฑ์ทุกอย่างก็ใช้ได้ดี


-1

มีความแตกต่างที่สำคัญสำหรับ getSize () การรวบรวมผลิตภัณฑ์จะไม่ถูกโหลด สำหรับ count () มันจะโหลดชุดผลิตภัณฑ์ทั้งหมด ดังนั้นสำหรับแค็ตตาล็อกขนาดใหญ่ไม่แนะนำให้ใช้ฟังก์ชั่นการนับในการรวบรวมใด ๆ


พูดแล้วในโพสต์ Marius ...
sv3n
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.