Frage

Hier ist mein Code:

$catIds = array(7,8,9);
$collection = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect("*");
    ->addAttributeToFilter('category_ids', array('nin' => $catIds));

Ich möchte alle Produkte nicht in Liste der Kategorie -IDs erhalten, aber mein Code hat nicht das erwartete Ergebnis erzielt. Bitte zeigen Sie mir den Weg, danke.

War es hilfreich?

Lösung

Sie müssen sich der Tabelle anschließen, in der die Kategorie/die Produktbeziehungen enthalten sind.

Eine Variation der Sammlung, mit der ich alle Produkte in einer Liste von Kategorien finde, sollte den Trick für Sie ausführen:

(ungetestet, aber sollte Sie auf den richtigen Weg bringen)

$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();

Ref: http://www.proxiblue.com.au/blog/collection_of_products_in_all_child_categories/

Andere Tipps

Der folgende Code funktioniert für Sie:

$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('*');

Ich habe eine etwas bessere Möglichkeit gefunden, dies mit einem Anti-Join (Magento 1.9) zu tun.

Vorteile dieses Ansatzes

Der Vorteil davon über die ursprüngliche Antwort ist, dass Sie keine falschen positiven positiven Aspekte erhalten und dass sie schneller und weniger fehleranfällig ist. Angenommen, Sie haben ein einzelnes Produkt:

  1. Shirt (in Kategorien: 1 | 2)

Du möchtest "Finden Sie alle Produkte nicht in category 3, und füge sie dann hinzu category 3". Also laufst du a NOT IN Abfrage, und es wird zwei Zeilen zurückgeben (name | category_id):

1. "Shirt" | 1
2. "Shirt" | 2

Keine große Sache, Magento wird immer noch das erste Ergebnis zurückgeben, und dann fügen Sie es hinzu. Außer! Beim zweiten Mal, dass diese Abfrage ausgeführt wird, haben Sie die gleichen Ergebnisse:

1. "Shirt" | 1
2. "Shirt" | 2

Und Magento wird Ihnen sagen, dass Sie dieses Shirt immer noch nicht hinzugefügt haben category 3. Dies liegt daran, dass ein Produkt zu mehreren Kategorien gehört, es mehrere Zeilen in der "CATALOG_PRODUCT_ENTITY" Tisch. Und so a LEFT JOIN wird mehrere Ergebnisse zurückgeben.

Dies ist unerwünscht, weil

  1. Ihr Ergebnissatz ist größer als nötig, was mehr Speicher als notwendig verbraucht. Besonders also, wenn Sie ein sehr großes Inventar von Tausenden von Gegenständen haben.
  2. Sie müssen einen zusätzlichen Einchecken in PHP durchführen, um festzustellen, ob die Ergebnisse falsch positiv sind (z. in_array($categoryThree, $product->getCategories())), was bedeutet, dass Sie unnötige Ergebnisse durchlaufen werden. Dadurch wird Ihr Skript/Code langsamer, insbesondere bei großen Beständen.

Lösung

// 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]
    ]);

Die generierte SQL -Abfrage sieht aus wie:

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`;

Erläuterung:

Angesichts des Produkts und des Produkts <=> Kategorie -Beziehungstabellen:

CATALOG_PRODUCT_ENTITY +-----------+ | ENTITY_ID | +-----------+ | 423 | | 424 | | 425 | +-----------+

Catalog_Category_Product +-------------+------------+ | CATEGORY_ID | PRODUCT_ID | +-------------+------------+ | 3 | 423 | | 123 | 424 | | 3 | 425 | +-------------+------------+

Ihre Frage sagt: "Gib mir alle Reihen in "CATALOG_PRODUCT_ENTITY", und fügen Sie die Spalte "category_id" von "ein "Catalog_Category_Product". Dann geben Sie mir einfach die Zeilen, die category_id = 124 ".

Weil es eine linke Verbindung ist, wird es immer die Zeilen von haben "CATALOG_PRODUCT_ENTITY". Für alle Zeilen, die nicht übereinstimmen können, wird es sein NULL:

Ergebnis +-------------+-------------+ | ENTITY_ID | CATEGORY_ID | +-------------+-------------+ | 423 | NULL | | 424 | 123 | | 425 | NULL | +-------------+-------------+

Von dort sagt die Frage dann, dann: "OK, jetzt gib mir alles, wo die category_id null ist".

Nicht so einfach wie es aussehen mag.

Hier ist die Option Group_Concat -basierte Option, da die Standardlimit (1024, aber natürlich erhöht werden kann) mit den durch Kommas -Set getrennten Produktkategorie -IDs in Ordnung sein sollte.

$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);
}

Auch (wenn Sie Group_Concat nicht mögen) können Sie verwenden, wo product_id nicht in einer Unterabfrage einer Produkt -IDs tatsächlich in Kategorien enthalten ist, die Sie ausschließen müssen (hier nicht geben).

Anti-Join-Ansatz von einem anderen Antworten wird auch funktionieren. In diesem Fall können Sie jedoch nicht leicht zusätzliche Bedingungen hinzufügen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit magento.stackexchange
scroll top