カテゴリにない製品をフィルタリングする方法は?
-
16-10-2019 - |
質問
これが私のコードです:
$catIds = array(7,8,9);
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect("*");
->addAttributeToFilter('category_ids', array('nin' => $catIds));
カテゴリIDのリストにないすべての製品を取得したいのですが、私のコードは期待されていませんでした。道を見せてください、ありがとう。
解決
カテゴリ/製品関係を保持するテーブルに参加する必要があります。
カテゴリのリスト内のすべての製品を見つけるために使用するコレクションのバリエーションは、次のことを行う必要があります。
(テストされていませんが、正しい軌道に乗るべきです)
$productCollection = Mage::getResourceModel('catalog/product_collection')
->setStoreId(0)
->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
->addAttributeToFilter('category_id', array('nin' => $catIds))
->addAttributeToSelect('*');
$productCollection->getSelect()->group('product_id')->distinct(true);
$productCollection->load();
参照: http://www.proxiblue.com.au/blog/collection_of_products_in_all_child_categories/
他のヒント
次のコードはあなたのために機能します:
$catIds = array(7,8,9);
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id = entity_id', null, 'left')
->addAttributeToFilter('category_id', array('nin' => array('finset' => $catIds)))
->addAttributeToSelect('*');
アンチオインを使用して、これを行うにはやや優れた方法が見つかりました(Magento 1.9)。
このアプローチの利点
元の答えに対するこの利点は、誤検知を得ることができず、結果としてより速く、エラーが発生しやすいことです。たとえば、単一の製品があるとします。
- シャツ(カテゴリ:1 | 2)
あなたはしたい 「すべての製品を見つけないでください category 3
, 、次にそれらを追加します category 3
". 。だからあなたはaを実行します NOT IN
クエリ、2行を返します (name | category_id)
:
1. "Shirt" | 1
2. "Shirt" | 2
大したことはありませんが、Magentoはまだ最初の結果を返すだけで、それを追加します。 それ外!このクエリが2回目に実行されると、同じ結果が得られます。
1. "Shirt" | 1
2. "Shirt" | 2
そして、Magentoはあなたがまだこのシャツを追加していないことをあなたに言うでしょう category 3
. 。これは、製品が複数のカテゴリに属している場合、に複数の行があるためです 「catalog_product_entity」 テーブル。そしてa LEFT JOIN
複数の結果を返します。
これは望ましくないからです
- 結果セットは必要以上に大きくなり、必要以上のメモリを使い果たします。特に、数千のアイテムの非常に大きなインベントリがある場合。
- 結果が誤検知であるかどうかを判断するには、PHPで追加のチェックを行う必要があります(例:
in_array($categoryThree, $product->getCategories())
)、つまり、不必要な結果をループすることを意味します。これにより、特に大きなインベントリを使用すると、スクリプト/コードが遅くなります。
解決
// 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 |
+-------------+------------+
あなたの質問は言っている、 「すべての行をください 「catalog_product_entity」, 、および「category_id」列に貼り付けます 「catalog_category_product」. 。次に、Category_id = 124 "の行を教えてください.
左結合なので、常にから行があります 「catalog_product_entity」. 。一致させることができないすべての行の場合、それは NULL
:
結果
+-------------+-------------+
| ENTITY_ID | CATEGORY_ID |
+-------------+-------------+
| 423 | NULL |
| 424 | 123 |
| 425 | NULL |
+-------------+-------------+
そこから、クエリは言います、 「わかりました、カテゴリ_IDがnullであるすべてを教えてください」.
見た目ほど簡単ではありません。
group_concatベースのオプションは、デフォルトの制限(1024はもちろん増加する可能性がある)であるため、ここには、コンマセットで区切られた製品カテゴリIDでは問題ありません。
$categoryIdsToExclude = array(1, 2, 4); // Category IDs products should not be in
$collection = Mage::getModel('catalog/product')->getCollection();
$selectCategories = $collection->getConnection()->select();
$selectCategories->from($collection->getTable('catalog/category_product'), array('product_id', 'category_id'));
$mysqlHelper = Mage::getResourceHelper('core');
$mysqlHelper->addGroupConcatColumn(
$selectCategories,
'category_ids_set',
'category_id',
','
);
$selectCategories->group('product_id');
$collection->getSelect()->joinLeft(
array('category_ids_set_table' => new Zend_Db_Expr('(' . $selectCategories->__toString() . ')')),
'category_ids_set_table.product_id = e.entity_id',
array('category_ids_set' => 'category_ids_set_table.category_ids_set')
);
foreach ($categoryIdsToExclude as $val) {
$collection->getSelect()->where('NOT FIND_IN_SET(?, category_ids_set)', $val);
}
また、(Group_Concatが気に入らない場合)Product_idが製品IDのサブクエリにない場合、実際には除外する必要があるカテゴリにあります(ここでは提供しません)。
別のアンチオインアプローチ 答え また動作します。しかし、この場合、追加の条件を簡単に追加することはできません。