Hi,
Custom Taxonomies are included in index (if that is what you set in Settings), but are not included in queries.
The problem is that you use $query_vars variable (stripped version of full WPQuery object, which is just fine) to build EP query, but in case of custom taxonomies, $query_vars does not include tax_query array, but instead you have "tax_slug" array in $query_vars and WPQuery->tax_query with WPTax object.
To be more specific, you have some sort of fix for empty tax_query array here https://github.com/10up/ElasticPress/blob/develop/includes/classes/Indexable/Post/Post.php#L702
The problem is that you are only handling core taxonomies, category and post_tag, and not custom taxonomies.
The result is a rebuilded tax_query array that does not include custom taxonomies, and you get all the posts returned.
I have reproduces this issue on several diferent environments with the same results.
I made a quick fix using filter ep_formatted_args, but you should rotate through all public taxonomies and use that for rebulding tax_query array (like you've done in the indexing phase).
WP 5.3
EP 3.2.6
I have the same issue:
I just tried installing ElasticPress on our WordPress WooCommerce site. It seems to be much faster! Thanks! However, I noticed I cannot search for Custom Product Attributes anymore. I can search for a category, and similar products will appear, but if I search for a Product Attribute value, it doesn't show any results. I have verified that the value is "Searchable" under Settings -> Search Fields & Weighting". I am using the plugin SearchWP Live Ajax Suggestions, to show live Ajax Suggestions as you type. If it doesn't have SearchWP, it will fallback to WP_Query which I assume elasitcpress.io uses (https://wordpress.org/plugins/searchwp-live-ajax-search/). Please let me know how I can fix this issue.
@ognjanovic feel free to include your workaround to get custom taxonomies in the query
You can use this hook to get prepared $formatted_args that is used for elastic queries
add_filter( 'ep_formatted_args', [ $this, 'my_ep_formatted_args' ], 1, 2 );
function my_ep_formatted_args( $formatted_args, $args ) {
global $wp_query, $wp_taxonomies;
// Just to avoid additional queries and parsers if they're not needed, but if this is search you should remove this from the list of conditions !$wp_query->is_search()
if ( !$wp_query->is_tag() && !$wp_query->is_category() && $wp_query->is_main_query() && $wp_query->is_archive() && !$wp_query->is_search() && !$wp_query->is_admin() ) {
//We want all public non-core taxonomies' names
$taxes = get_taxonomies( array( 'public' => true, '_builtin' => false ), 'names' );
// Fix
// if $wp_query->query_vars['post_type'] is not set, ElasticPress sets it to post_type = post, and for tax queries that should not be set (because we want all public post types related to specific taxonomy to be queried)
// for my specific case, this does the dirty trick, but you should use $wp_taxonomies[$taxonomy]->object_type to get post types related to your taxonomy in the foreach below
if ( empty( $wp_query->query_vars['post_type'] ) ) {
// This holds the post type filter $formatted_args['post_filter']['bool']['must'][0]
unset( $formatted_args['post_filter']['bool']['must'][0] );
}
foreach ( $taxes as $taxonomy ) {
// We have to check if there is a taxonomy array in $wp_query->query_vars
if ( !empty( $wp_query->query_vars[$taxonomy] ) ) {
$new_formated_args = array(
'bool' => array(
'must' => array(
'terms' => array(
'terms.' . $taxonomy . '.slug' => array(
$wp_query->query_vars[$taxonomy]
)
)
)
)
);
array_unshift( $formatted_args['post_filter']['bool']['must'], $new_formated_args );
}
}
}
return $formatted_args;
}`
You can see how the $formatted_args is build by analysing the plugin code, but in general it's not so complicated, just focus on this part of the array $formatted_args['post_filter']['bool']['must']
This is far from my version of a good written code, but it works, and it's a quick fix that I had to pull :D
Hope it helps.
Thanks @ognjanovic ! Would this workaround work out of the box with WooCommerce products/variable products?
Also, any updates from plugin authors related to this? @elasticpress-jenkins
As far as I know, WooCommerce uses taxonomies for attributies wich are again used to generate variable products (usually), so this should work more or less out fo the box :D
You can setup a staging woocommerce instance on the same server and connect it to the same elasticsearch instance and use this code since this doesn't affect elasticsearch index, it just parses query sent to elastic so we could get relevant results.
Cool thanks.
Just for reference, this is the code I end up using. I'll be testing on production, and if you don't hear back from me, it's because it's working ;)
add_filter( 'ep_formatted_args', 'my_ep_formatted_args', 1, 2 );
function my_ep_formatted_args( $formatted_args, $args ) {
global $wp_query, $wp_taxonomies;
// Just to avoid additional queries and parsers if they're not needed, but if this is search you should remove this from the list of conditions !$wp_query->is_search()
if ( !$wp_query->is_tag() && !$wp_query->is_category() && $wp_query->is_main_query() && $wp_query->is_archive() && !$wp_query->is_search() && !$wp_query->is_admin() ) {
//We want all public non-core taxonomies' names
$taxes = get_taxonomies( array( 'public' => true, '_builtin' => false ), 'names' );
// Fix
// if $wp_query->query_vars['post_type'] is not set, ElasticPress sets it to post_type = post, and for tax queries that should not be set (because we want all public post types related to specific taxonomy to be queried)
// for my specific case, this does the dirty trick, but you should use $wp_taxonomies[$taxonomy]->object_type to get post types related to your taxonomy in the foreach below
if ( empty( $wp_query->query_vars['post_type'] ) ) {
// This holds the post type filter $formatted_args['post_filter']['bool']['must'][0]
unset( $formatted_args['post_filter']['bool']['must'][0] );
}
foreach ( $taxes as $taxonomy ) {
// We have to check if there is a taxonomy array in $wp_query->query_vars
if ( !empty( $wp_query->query_vars[$taxonomy] ) ) {
$new_formated_args = array(
'bool' => array(
'must' => array(
'terms' => array(
'terms.' . $taxonomy . '.slug' => array(
$wp_query->query_vars[$taxonomy]
)
)
)
)
);
array_unshift( $formatted_args['post_filter']['bool']['must'], $new_formated_args );
}
}
}
return $formatted_args;
}
Unfortunately this fix didn't solve the issue. On my shop, when filtering products for say "Diamonds" it says "No results found".
I mean, you'll have to debug the query and check it vs this code, especially vs this conditions
if ( !$wp_query->is_tag() && !$wp_query->is_category() && $wp_query->is_main_query() && $wp_query->is_archive() && !$wp_query->is_search() && !$wp_query->is_admin() )
At least you should remove these two
$wp_query->is_archive() && !$wp_query->is_search()
Maybe even this one $wp_query->is_main_query()
@ognjanovic can you post some steps to reproduce the issues? Are you saying the following isn't supported:
new WP_Query( [
'custom_tax_name' => 'slug',
] );
Try to use it on any custom tax archive page for example, you鈥檒l get all posts, not just the ones with that custom tax.
I didn鈥檛 try using it on custom queries, just reproduced the issue on builtin wp queries.
Hi @tlovett1 ,
As far as I can see you didn't fix custom taxonomy query bug in the latest release?
@simplenotezy do you have the WooCommerce Feature for ElasticPress active? It handles all the common WooCommerce attributes and enables support for Custom Product Attributes. If you've got this active and it's still not working, could you please install the Debug Bar and Debug Bar ElasticPress plugins and share the results of the JSON queries that are being sent to your Elasticsearch server?
@ognjanovic Can you please do the same with a taxonomy page, and also include the WP_Query object from the Debug Bar ElasticPress output along with the JSON going to the server?
Thank you!
@ognjanovic can you also post a screenshot of the Weighting Engine settings for the custom post type that you're looking at the tax archive for?
Hi @brandwaffle ,
Here is the screenshot
https://www.dropbox.com/s/a73l1pjdeyvcch1/Screenshot_2019-12-27%20ElasticPress%20Setup%20%E2%80%B9%20Dnevni%20list%20Danas%20%E2%80%94%20WordPress.png?dl=0
This is the Query Args
array(67) {
["kolumnista"]=>
string(20) "aleksandar-milosevic"
["error"]=>
string(0) ""
["m"]=>
string(0) ""
["p"]=>
int(0)
["post_parent"]=>
string(0) ""
["subpost"]=>
string(0) ""
["subpost_id"]=>
string(0) ""
["attachment"]=>
string(0) ""
["attachment_id"]=>
int(0)
["name"]=>
string(0) ""
["pagename"]=>
string(0) ""
["page_id"]=>
int(0)
["second"]=>
string(0) ""
["minute"]=>
string(0) ""
["hour"]=>
string(0) ""
["day"]=>
int(0)
["monthnum"]=>
int(0)
["year"]=>
int(0)
["w"]=>
int(0)
["category_name"]=>
string(0) ""
["tag"]=>
string(0) ""
["cat"]=>
string(0) ""
["tag_id"]=>
string(0) ""
["author"]=>
string(0) ""
["author_name"]=>
string(0) ""
["feed"]=>
string(0) ""
["tb"]=>
string(0) ""
["paged"]=>
int(0)
["meta_key"]=>
string(0) ""
["meta_value"]=>
string(0) ""
["preview"]=>
string(0) ""
["s"]=>
string(0) ""
["sentence"]=>
string(0) ""
["title"]=>
string(0) ""
["fields"]=>
string(0) ""
["menu_order"]=>
string(0) ""
["embed"]=>
string(0) ""
["category__in"]=>
array(0) {
}
["category__not_in"]=>
array(0) {
}
["category__and"]=>
array(0) {
}
["post__in"]=>
array(0) {
}
["post__not_in"]=>
array(0) {
}
["post_name__in"]=>
array(0) {
}
["tag__in"]=>
array(0) {
}
["tag__not_in"]=>
array(0) {
}
["tag__and"]=>
array(0) {
}
["tag_slug__in"]=>
array(0) {
}
["tag_slug__and"]=>
array(0) {
}
["post_parent__in"]=>
array(0) {
}
["post_parent__not_in"]=>
array(0) {
}
["author__in"]=>
array(0) {
}
["author__not_in"]=>
array(0) {
}
["no_found_rows"]=>
bool(true)
["ep_integrate"]=>
bool(true)
["ignore_sticky_posts"]=>
bool(false)
["suppress_filters"]=>
bool(false)
["cache_results"]=>
bool(false)
["update_post_term_cache"]=>
bool(true)
["lazy_load_term_meta"]=>
bool(true)
["update_post_meta_cache"]=>
bool(true)
["post_type"]=>
string(0) ""
["posts_per_page"]=>
int(15)
["nopaging"]=>
bool(false)
["comments_per_page"]=>
string(2) "50"
["taxonomy"]=>
string(10) "kolumnista"
["term"]=>
string(20) "aleksandar-milosevic"
["order"]=>
string(4) "DESC"
}
And this is Query Body sent to Elastic
{
"from": 0,
"size": 15,
"sort": [
{
"post_date": {
"order": "desc"
}
}
],
"query": {
"match_all": {
"boost": 1
}
},
"post_filter": {
"bool": {
"must": [
{
"terms": {
"post_type.raw": [
"post"
]
}
},
{
"terms": {
"post_status": [
"publish",
"acf-disabled"
]
}
}
]
}
}
}
Most helpful comment
You can use this hook to get prepared $formatted_args that is used for elastic queries
add_filter( 'ep_formatted_args', [ $this, 'my_ep_formatted_args' ], 1, 2 );function my_ep_formatted_args( $formatted_args, $args ) {
global $wp_query, $wp_taxonomies;
}`
You can see how the $formatted_args is build by analysing the plugin code, but in general it's not so complicated, just focus on this part of the array $formatted_args['post_filter']['bool']['must']
This is far from my version of a good written code, but it works, and it's a quick fix that I had to pull :D
Hope it helps.