After digging into the Magento Core code an additional one and a half day i finally found a solution for my issue.
If you expect a short answer here, or a simple fix, lets just say, "there is none", at least in the way its currently implemented in the Magento2 Core.
A lot of the used classes are deprecated, so lets hope this mess is cleaned up in some future release.
Digging further into the functionality of the
i first found out that the problem, the Fulltext Collection's
addFieldToFilter method does not support
OR-conditions lays not in the Fulltext Collection itself, but in the Magento2 Cores search-engine.
Have a look at the method
Magento\Framework\Search\Search::addFieldToFilter which is called during the responsible methods of the Fulltext Collection (i won't show all the callstacks here). This method has nearly the same functionality as the Fulltext Collection
addFieldToFilter method and also does not support OR-conditions.
So let's dig deeper into how that search actually works...
Magento\Framework\Search\Search::search a search request is built using the SearchRequestBuilder adding all the filters and so on from the searchCriteria to the request object. The search is then performed using
Magento\Search\Model\SearchEngine::search just passes the the SearchRequest object to the SearchAdapter creating the adapter using the AdapterFactory
Magento\Framework\Search\Adapter\Mysql\Adapter is the SearchAdapter which is used (and which is deprecated already since
102.0.0). But still here all the magic happens.
The search builds up an SQL query using the
Magento\Framework\Search\Adapter\Mysql\Mapper and creates a new temporary mysql table with the results of the searchRequest.
To get some steps back, in the Fulltext Collection this temporary table is inner joined to the product collection select, filtering the results from the product collection by the results in the search_tmp table.
If you follow the call stack of
Magento\Framework\Search\Adapter\Mysql\Adapter a bit further, at the end you may find the 2 methods i modified to fix the issue i had:
Magento\CatalogSearch\Model\Search\FilterMapper\CustomAttributeFilter::apply called in
(also deprecated since
This method is responsible for joining the
catalog_product_index_eav tables for each of your custom attributes. Still without filters, except if only one custom attribute filter is selected, then it's also already handling the filtering by that attribute.
While this class by default uses
inner joins for my case i needed
left joins, to join both new attributes to be able to build a or condition, even if one of both attributes does not have a value for a product.
So i decided to modify this by an after plugin to modify the joins of my custom attributes to
left join and also to join an additional table if one of the 2 attributes are applied as filters.
Magento\CatalogSearch\Model\Adapter\Mysql\Filter\Preprocessor::process called in
(also deprecated since
This method is responsible for building the
WHERE part in the sql select.
It is called once for each filter applied and returns a string containing a single part of the
This parts are afterwards joined to build the full
WHERE part of the query.
So i decided to modify this as well by using an after plugin extending the base condition by the OR on the other table which is joined in the other plugin.
That's it, i know, it's dirty, but sadly still the cleanest way i found after some days of research.
I will leave this question still open for the next days if someone has a better solution in mind; and will approve my own answer in a few days if not.