2

I'm trying to add some extra filterable information in the graphql products Query related to the categories.

More specifically I want to add the slug and the category id of all associated product categories.

I've created my resolver

class CategorySlug implements ResolverInterface
{
    private $categoryRepository;

    public function __construct(CategoryRepositoryInterface $categoryRepository)
    {
        $this->categoryRepository = $categoryRepository;
    }

    /**
     * @inheritdoc
     */
    public function resolve(
        Field       $field,
                    $context,
        ResolveInfo $info,
        array       $value = null,
        array       $args = null
    )
    {
        if (!isset($value['model'])) {
            throw new LocalizedException(__('"model" value should be specified'));
        }

        /* @var $product Product */
        $product = $value['model'];
        $categoryIds = $product->getCategoryIds();
        $slugs = [];
        foreach($categoryIds as $categoryId){
            $category = $this->categoryRepository->get($categoryId);
            $slugs[] = ['slug' => $category->getUrlKey(), 'id' => $category->getId()];
        }
        return $slugs;

    }
}

And I've extended my schema.graphqsl file to do this

# noinspection GraphQLUnresolvedReference

interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes.") {
    brand: Int @doc(description: "Brand Name based on manufacturer attribute") @resolver(class: "Vendor\\GraphQlExtend\\Model\\Resolver\\Product\\Brand")
    category_slugs: [CategorySlug] @doc(description: "Search based on category slug") @resolver(class: "Vendor\\GraphQlExtend\\Model\\Resolver\\Product\\CategorySlug")
}

input BrandInput @doc(description:"Comment for FilterTypeInput") {
    eq: Int @doc(description:"Equal")
    in: [Int]
    neq: Int
    notnull: String
    null: String
    nin: [Int]
}

input CategorySlugInput {
    eq: String
}

input ProductFilterInput {
    brand: BrandInput @doc(description: "Brand ID")
    category_slugs: CategorySlugInput @doc(description: "Category slug")
}

type Query {
    filteredCustomerOrders(
        filter: FilteredCustomerOrdersFilterInput,
        pageSize: Int = 20,
        currentPage: Int = 1
    ): FilteredCustomerOrdersData
    @resolver(class: "Vendor\\GraphQlExtend\\Model\\Resolver\\Customer\\Orders\\FilteredCustomerOrders")
    @cache(cacheable: false)
}

type FilteredCustomerOrdersData {
    totalCount: Int
    items: [CustomerOrder]
}

input FilteredCustomerOrdersFilterInput {
    status: FilterTypeInput
}

type CategoryTree implements CategoryInterface{
    thumbnail_url: String @resolver(class: "Vendor\\GraphQlExtend\\Model\\Resolver\\Category\\ThumbnailResolver")
}

type CategorySlug {
    id: Int
    slug: String
}

Now my Query will yield the correct field data like this

{
    products(
        filter: {
        }
        pageSize: 2
    ) 
    {
        total_count,
        items
        {
            id,
            category_slugs
            {   
                id,
                slug
            }
        } 
    }
}

Result

{
    "data": {
        "products": {
            "total_count": 1544,
            "items": [
                {
                    "id": 7690,
                    "category_slugs": [
                        {
                            "id": 62,
                            "slug": "straps-and-stands"
                        },
                        {
                            "id": 80,
                            "slug": "all-products"
                        }
                    ]
                },
                {
                    "id": 8794,
                    "category_slugs": [
                        {
                            "id": 24,
                            "slug": "gaming-ar"
                        },
                        {
                            "id": 80,
                            "slug": "all-products"
                        }
                    ]
                }
            ]
        }
    }
}

The problem I'm facing is trying to filter the results based on the slug.

For example to show only the results where "slug": "gaming-ar"

Because my field category_slugs is an array I can't really filter it properly.

A query like this

{
    products(
        filter: {
            category_slugs: {
                eq: "accessories"                
            }
        }
        pageSize: 2
    ) 
    {
        total_count,
        items
        {
            id,
            category_slugs
            {   
                id,
                slug
            }
        } 
    }
}

Yields an error

{
    "errors": [
        {
            "debugMessage": "The \"category_slugs\" attribute name is invalid. Reset the name and try again.",
            "message": "Internal server error",
            "category": "internal",
            "locations": [
                {
                    "line": 2,
                    "column": 5
                }
            ],
            "path": [
                "products"
            ]
        }
    ],
    "data": {
        "products": null
    }
}

Any ideas how to modify my graphql schema to support a query like that?

2 Answers 2

0

To my knowledge, If you need to have a product filter you should create the product attribute and set any of the below two configuration

  • Set the Use in Layered Navigation field to Filterable (with results) or Filterable (no results).
  • Set the Use in Search and Visible in Advanced Search fields to Yes.

Only then magento will index the attribute’s contents and making the data available for search.

1
  • Thank you for the answer but it's a bit off topic. I've already created attributes that are filterable to add them with a Custom Resolver but the goal here isn't just to compare a single attribute. It's to link Custom Type Arrays to the product and filter on the Arrays themselves based on their respective fields.
    – gabtzi
    Commented Oct 14, 2022 at 6:22
0

did you find a solution to it? I am facing a similar problem right now

1
  • Unfortunately no, I had to go the inverse way and filter a category by url_key and then get the children products for it instead, but this meant extra queries :(
    – gabtzi
    Commented Apr 21, 2023 at 7:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.