__Have you searched for similar issues before submitting this one?__
I have found this post - https://github.com/10up/ElasticPress/issues/1154 - but this is a bit broader than what I am looking for, which is a basic toggle of functionality
__Is this a bug, question or feature request?__
Question
__Describe the issue you encountered:__
By default, with elasticpress enabled, search results give an OR result - using the standard wordpress search form. Can it be changed, by default, to be AND?
For example:
searching London Cinemas gives all posts with london OR cinema
can this be changed easily to give posts with London AND cinema?
Hi @zandergrin you can currently change this using some code--instructions are here https://www.elasticpress.io/blog/2019/02/custom-search-with-elasticpress-how-to-limit-results-to-full-text-matches/
We are also considering adding a toggle feature for this in the ElasticPress dashboard.
Thanks @brandwaffle, I did see and it's not quite what I'm after - that's a full text match, or exact match... we're after and AND, so they can be in separate places.
So those instructions seem to be to only show exact matches for "London Cinema"
We want posts which contain the words London AND Cinema, but not necessarily together... unless I'm misreading the instructions.
A toggle would be incredible!
@zandergrin that change will match on any posts with London and Cinema anywhere in a single field, and will prioritize results based on how close the results are. So "London Cinema" will appear above "London has a variety of Cinema locations" but both will appear in results.
Thanks @brandwaffle - ah I misread that content then... actually that works brilliantly, but with one issue. It stops the correction for misspelling working...
So before this change you could misspell London as Londn and it would find results
after this change it no longer recognises the misspelling
I would like to chip in here too. I have been having a play around with this scenario. I have caught on to one thing @brandwaffle mentioned a short while ago :
that change will match on any posts with London and Cinema anywhere in a single field
Is it a viable situation to have it match across fields? So if London was in the title but Cimema was a category term it would still return the post. Or is that going against the basic premise?
@JoshuaCrewe it's definitely possible, but it does take a bit of code to filter the typical query. For what you're describing you want to use the cross_fields (instead of phrase) multi_match query type. You can read more about how that works here https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#type-cross-fields
We haven't built this into the plugin since it has ramifications when it comes to the custom weighting engine and we've historically taken the "search for full matches within a single field and add them to the score based on the weighting" approach vs the cross-field approach, because the former is a lot more generic and the latter requires some additional logic (and vs or, for example).
You can change the query type via this filter, which takes the entire incoming query and lets you change any paramater in the array before it gets sent to Elasticsearch: https://github.com/10up/ElasticPress/blob/941b5c69e1b0622babe3c54852e03a1a91b70d33/includes/classes/Indexable/Post/Post.php#L1084
Hope this helps!
@brandwaffle thanks for the response! I think I am following your logic. I am going to dig through the documentation you linked to and see if I can effect a change in results. Win or lose I will report back here for completeness.
So in the end I was able to use ep_formatted_args_query filter to replace the query that was being run. Using the debug bar was really helpful to see what what happening under the hood. I was able to set the type to cross fields, include the fields I wanted to use in the search and define the operator as and.
I get the results that I wanted to get but I feel a bit uneasy overwriting the query that was there. On this occasion the use case is really specific so I can monitor if somethig else got broken.
@JoshuaCrewe don't feel uneasy, feel proud! 馃槃
Awesome to hear this worked, and you should be totally fine with a custom query--we do it all the time for specific use-cases just like you're doing in this case. If you do find it doing weird things, I'd recommend starting with some additional tests in your code to check for the specific query you want to override and otherwise not applying any customizations.
I'll close this ticket for now, but if you do run into any issues please feel free to re-open and add more info!
Thanks for your help @brandwaffle - and just to add, I think adding as a toggle feature in the backend would be really useful.
Most helpful comment
@JoshuaCrewe it's definitely possible, but it does take a bit of code to filter the typical query. For what you're describing you want to use the
cross_fields(instead ofphrase) multi_match querytype. You can read more about how that works here https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html#type-cross-fieldsWe haven't built this into the plugin since it has ramifications when it comes to the custom weighting engine and we've historically taken the "search for full matches within a single field and add them to the score based on the weighting" approach vs the cross-field approach, because the former is a lot more generic and the latter requires some additional logic (and vs or, for example).
You can change the query
typevia this filter, which takes the entire incoming query and lets you change any paramater in the array before it gets sent to Elasticsearch: https://github.com/10up/ElasticPress/blob/941b5c69e1b0622babe3c54852e03a1a91b70d33/includes/classes/Indexable/Post/Post.php#L1084Hope this helps!