मैंने ऐसा करने का एक बेहतर तरीका पाया है, एंटी-जॉइन (Magento 1.9) का उपयोग करते हुए।
इस दृष्टिकोण के लाभ
मूल उत्तर की तुलना में इसका लाभ यह है कि आपको झूठी सकारात्मकता नहीं मिलेगी, और परिणामस्वरूप यह तेज और कम त्रुटि वाला होता है। उदाहरण के लिए, मान लीजिए कि आपके पास एक ही उत्पाद है:
- शर्ट (श्रेणियों में: 1 | 2)
आप "सभी उत्पादों को नहीं ढूंढनाcategory 3
category 3
चाहते हैं , फिर उन्हें जोड़ें " । इसलिए आप एक NOT IN
क्वेरी चलाते हैं , और यह दो पंक्तियों को लौटा देगा (name | category_id)
:
1. "Shirt" | 1
2. "Shirt" | 2
कोई बड़ी बात नहीं, Magento अभी भी केवल पहला परिणाम लौटाएगा, और फिर आप इसे जोड़ देंगे। को छोड़कर ! दूसरी बार यह क्वेरी चलने पर, आपके पास समान परिणाम होंगे:
1. "Shirt" | 1
2. "Shirt" | 2
और Magento आपको बताएगा कि आपने अभी भी इस शर्ट को नहीं जोड़ा है category 3
। ऐसा इसलिए है क्योंकि जब कोई उत्पाद कई श्रेणियों का होता है, तो उनके पास "कैटलॉग_प्रोडक्ट_एंटिटी" तालिका में कई पंक्तियाँ होंगी । और इसलिए एक LEFT JOIN
से अधिक परिणाम आएंगे।
यह अवांछनीय है क्योंकि
- आपका परिणाम सेट आवश्यकता से अधिक बड़ा होगा, जो आवश्यकता से अधिक मेमोरी का उपयोग करेगा। विशेष रूप से इसलिए यदि आपके पास हजारों मदों की एक बहुत बड़ी सूची है।
- परिणामों को गलत सकारात्मक (उदाहरण के लिए
in_array($categoryThree, $product->getCategories())
) हैं, तो यह निर्धारित करने के लिए आपको PHP में एक अतिरिक्त जांच करने की आवश्यकता होगी , जिसका अर्थ है कि आप अनावश्यक परिणामों के माध्यम से लूप करेंगे। यह आपकी स्क्रिप्ट / कोड को धीमा कर देगा, विशेष रूप से बड़े आविष्कारों के साथ।
समाधान
// All products not in this category ID
$notInThisCatId = '123';
$filteredProducts = Mage::getModel('catalog/product')->getCollection();
$filteredProducts
->joinField('category_id', 'catalog_category_product', 'category_id', 'product_id=entity_id', ['category_id'=>$notInThisCatId], 'left');
$filteredProducts
->addAttributeToFilter('category_id', [
['null' => true]
]);
उत्पन्न SQL क्वेरी इस तरह दिखाई देगी:
SELECT
DISTINCT `e`.*, `at_category_id`.`category_id`
FROM `catalog_product_entity` AS `e`
LEFT JOIN `catalog_category_product` AS `at_category_id`
ON (at_category_id.`product_id`=e.entity_id) AND (at_category_id.category_id = '123')
WHERE (at_category_id.category_id IS NULL)
GROUP BY `e`.`entity_id`;
स्पष्टीकरण:
उत्पाद और उत्पाद को देखते हुए <=> श्रेणी संबंध तालिकाएँ:
catalog_product_entity
+-----------+
| ENTITY_ID |
+-----------+
| 423 |
| 424 |
| 425 |
+-----------+
catalog_category_product
+-------------+------------+
| CATEGORY_ID | PRODUCT_ID |
+-------------+------------+
| 3 | 423 |
| 123 | 424 |
| 3 | 425 |
+-------------+------------+
आपकी क्वेरी कह रही है, "मुझे " कैटलॉग_प्रोडक्ट_एंटिटी " में सभी पंक्तियां दें , और " कैटगरी_आईडी " कॉलम पर " कैटलॉग_कैटरोरी_प्रोडक्ट " से पेस्ट करें । इसके बाद बस मुझे उस श्रेणी_आईडी = 124" की पंक्तियां दें ।
क्योंकि यह लेफ्ट जॉइन है, इसलिए इसमें हमेशा "कैटलॉग_प्रोडक्ट_एंटिटी" से पंक्तियाँ होंगी । किसी भी पंक्तियों के लिए जिसका मिलान नहीं किया जा सकता है, यह होगा NULL
:
परिणाम
+-------------+-------------+
| ENTITY_ID | CATEGORY_ID |
+-------------+-------------+
| 423 | NULL |
| 424 | 123 |
| 425 | NULL |
+-------------+-------------+
वहां से, क्वेरी तब कहती है, "ठीक है, अब मुझे वह सब कुछ दे दो जहाँ category_id NULL है" ।