마 젠토 2 : 제품 리포지토리, 필터 그룹 및`AND`


12

제품 저장소를 사용하여 제품 목록을 가져 오려고합니다. AND기준 과 결합 된 두 개의 필터를 기반으로 가져오고 싶지만 작동하지 않는 것 같습니다. 필터 그룹의 작동 방식을 이해하지 못합니까? 아니면이 버그가보고되어야합니까?

구체적으로, (간단 성을 위해 잘못된 예제) 필터 빌더, 필터 그룹 빌더 및 검색 기준 빌더를 삽입하는 생성자가 있습니다.

public function __construct(
    \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
    \Magento\Framework\Api\FilterBuilder $filterBuilder,
    \Magento\Framework\Api\Search\FilterGroupBuilder $filterGroupBuilder 
)
{
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->filterBuilder         = $filterBuilder;
    $this->filterGroupBuilder    = $filterGroupBuilder;
}

그런 다음 나중에 메소드에서 필터 빌더를 사용하여 두 개의 필터를 빌드합니다.

    $filter1 = $this->filterBuilder->setField('sku')
            ->setValue('24-MB01')
            ->setConditionType('eq')
            ->create();

    $filter2 = $this->filterBuilder->setField('sku')
            ->setValue('WT08-XS-Black')
            ->setConditionType('eq')
            ->create();

그런 다음 필터 그룹 빌더를 사용하여이 두 필터로 구성된 필터 그룹을 빌드하십시오.

    $filter_group = $this->filterGroupBuilder
        ->addFilter($filter1)
        ->addFilter($filter2)
        ->create();

그런 다음 검색 기준 빌더를 사용하고 필터 그룹을 설정했습니다.

    $criteria = $this->searchCriteriaBuilder
        ->setFilterGroups([$filter_group])
        ->setPageSize(100)
        ->create();            
    return $criteria

마지막 으로이 기준을 제품 저장소와 함께 사용할 때 (다른 곳에서 사용하여 혼란을 피하기 위해 생성자와 di를 제외)

/* @var Magento\Catalog\Api\ProductRepositoryInterface */
$list = $productRepository->getList($searchCriteria);  

전화는 성공적 이지만 두 제품을 다시 얻습니다. 즉, SKU 필터가로 적용 OR되지 않았습니다 AND. 이 쿼리가 아무것도 반환하지 않을 것으로 기대합니다.

Magento\Catalog\Api\ProductRepository클래스를 파고 컬렉션의 선택문을 살펴보면

protected function addFilterGroupToCollection(
    \Magento\Framework\Api\Search\FilterGroup $filterGroup,
    Collection $collection
) {
    //...
    if ($fields) {
        $collection->addFieldToFilter($fields);
    }

    //printf lives in my heart forever
    echo($collection->getSelect()->__toString());
    exit;
}               

추가 된 기준이 OR

SELECT `e`.*, IF(at_status.value_id > 0, at_status.value, at_status_default.value) AS `status`, IF(at_visibility.value_id > 0, at_visibility.value, at_visibility_default.value) AS `visibility` 

FROM `catalog_product_entity` AS `e` 

INNER JOIN `catalog_product_entity_int` AS `at_status_default` ON (`at_status_default`.`entity_id` = `e`.`entity_id`) AND (`at_status_default`.`attribute_id` = '94') AND `at_status_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_status` ON (`at_status`.`entity_id` = `e`.`entity_id`) AND (`at_status`.`attribute_id` = '94') AND (`at_status`.`store_id` = 1) 

INNER JOIN `catalog_product_entity_int` AS `at_visibility_default` ON (`at_visibility_default`.`entity_id` = `e`.`entity_id`) AND (`at_visibility_default`.`attribute_id` = '96') AND `at_visibility_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_visibility` ON (`at_visibility`.`entity_id` = `e`.`entity_id`) AND (`at_visibility`.`attribute_id` = '96') AND (`at_visibility`.`store_id` = 1)

WHERE ((`e`.`sku` = '24-MB01') OR (`e`.`sku` = 'WT08-XS-Black')) 

이것이 버그입니까? 이 작업을 수행 할 수있는 방법이 있습니까 (제품 컬렉션에 직접 의존하고 리포지토리를 버리는 방법) 있습니까?


2
아직 개인적으로이 영역을 살펴 보지는 않았지만 cyrillschumacher.com/2015/01/02/… 가 유용 할 것입니다.
Alan Kent

답변:


15

\Magento\Framework\Api\Search\FilterGroup말한다 (클래스 phpDoc) 의 실제 주석 :

논리 OR을 사용하여 둘 이상의 필터를 그룹화

즉, 각각 하나의 필터로 두 개의 그룹을 만들어야합니다.


이 문제를 해결해 주셔서 감사합니다. Magento 2
:-P

2

Magento 2에서는 동일한 필터가 모두 연산자를 FilterGroup사용하여 추가됩니다 OR. 그러나 모든 연산자는 연산자를 FilterGroup사용하여 추가됩니다 AND. 따라서 FilterGroup아래와 같이 여러 개를 추가해야 합니다.

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$searchCriteria = $objectManager->create('\Magento\Framework\Api\SearchCriteria');
$filter = $objectManager->create('\Magento\Framework\Api\Filter');
$filter->setField('category_id');
$filter->setValue(array(1, 2, 3));
$filter->setConditionType('in');

$filterGroup = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroup->setFilters([$filter]);

$filterEnabled = $objectManager->create('\Magento\Framework\Api\Filter');
$filterEnabled->setField('status');
$filterEnabled->setValue(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
$filterEnabled->setConditionType('eq');

$filterGroupEnabled = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroupEnabled->setFilters([$filterEnabled]);


$searchCriteria->setFilterGroups([$filterGroup, $filterGroupEnabled]);

검색 기준에 대한 자세한 내용과 논리적 조합은 Magento-2 검색 기준 에서 찾을 수 있습니다


이것은 올바르지 않습니다. 논리는 리포지토리별로 구현됩니다.
Alan Storm

안녕 @ 앨런 스톰, 이것은 테스트 솔루션입니다. Magento 2.1.0의 기본 저장소에 대해 테스트했습니다. 잘못 선언 할만한 근거가 있습니까?
Kamal Singh


@ 앨런 스톰, 그게 내 대답에서 언급 한 것입니다. 모든 필터 그룹은 AND 연산자를 사용하여 결합되고 단일 필터 그룹의 모든 필터는 Magento 2 검색 기준 문서에 따라 OR 연산자를 사용하여 결합됩니다. 이 솔루션은 기본 저장소로 테스트되었다고 언급했습니다. 귀하의 의견에 따라이 답변이 잘못된 이유는 무엇입니까?
Kamal Singh

@KamelSingh 내가 링크 한 버그 보고서를 읽었습니까? 의도 된 동작에 관계없이 필터 및 필터 그룹의 동작은 궁극적으로 이들이있는 리포지토리의 동작에 따라 달라집니다.
Alan Storm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.