How to Enable 'eq' Filter GraphQL Search for an Custom Attribute of Type Text in Magento 2
Generally there are 3 types of filter that you can use with graphql search and these filter type depends upon your attribute configuration.
FilterEqualTypeInput
- Input type is set to Yes/No, Select, or Multiple select. Your filter can contain theeq
orin
attribute. Use theeq
attribute to exactly match the specified string. Use thein
attribute to filter on a comma-separated list of values.FilterMatchTypeInput
- Input type is set to Text Field or Text Area. Your filter must contain thematch
attribute, which will return all items that partially fuzzy match the specified string.FilterRangeTypeInput
- Input type is set to Price or Date. Your filter can contain one or both of theto
andfrom
attributes, which serve to provide a range of values to filter on.
If, for any reason, you require the text attribute to support the "eq" filter, you can follow the steps below:
Text attributes are using match
attributes OOTB. But Magento leaves open door to change this behavior by injecting the custom attribute using the below classes. This behaviour we can see for sku
,url_key etc.
Magento\CatalogGraphQl\Model\Config\FilterAttributeReader
- injectstyle_code
toprivate $exactMatchAttributes = ['sku'];
allows to change graphQL queries to useeq
attributeMagento\CatalogGraphQl\Plugin\Search\Request\ConfigReader
- injectstyle_code
to “exactMatchAttribute“ change request guery for Elasticsearch.
Changel Graphql query to use eq filter
Update the di.xml file to inject the custom attribute to the variable exactMatchAttributes to the class Magento\CatalogGraphQl\Model\Config\FilterAttributeReader
<type name="Magento\CatalogGraphQl\Model\Config\FilterAttributeReader">
<arguments>
<argument name="exactMatchAttributes" xsi:type="array">
<item name="custom_attribute" xsi:type="string">style_code</item>
</argument>
</arguments>
</type>
Change request query for Elasticsearch
Update the di.xml file to inject the custom attribute to the variable exactMatchAttributes in the class Magento\CatalogGraphQl\Plugin\Search\Request\ConfigReader
<type name="Magento\CatalogGraphQl\Plugin\Search\Request\ConfigReader">
<arguments>
<argument name="exactMatchAttributes" xsi:type="array">
<item name="style_code" xsi:type="string">style_code</item>
</argument>
</arguments>
</type>
Verify Elasticsearch Keyword mapping
If an attribute needs to be searched with eq filter the attribute should have the keyword index mapping in the ElasticSearch.
This can be vieified iwth the below curl comand
curl --location --request GET 'http://localhost:9200/*/_mapping/field/url_key'
{
"mappings": {
"url_key": {
"full_name": "url_key",
"mapping": {
"url_key": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
},
"copy_to": [
"_search"
]
}
}
}
}
}
Generally for all the attributes where the backend_type is "text", The keword mapping would not be set by default.
Here the attribute "test_text" will not have a keword mapping in elasticsearch so we cannot use "eq" filter.
To know more preciesly on where keword mapping will not be added refer the below file.
\Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\StaticField::getField
But you can still make this type of attribute to support keyword mapping by updating the attribute index mapping. The index mapping for an attribute this set in the below method. So we can crete the afterPlugin for this method and have the mapping updated.
\Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\StaticField::getFields