When I use the Filter - Search element I am able to do beautiful things with it. However I have one big problem.
If I have a result titled “Big Red Button“ and and search for “Big Button” it doesn’t gives the “Big Red Button“ as a result. I can’t expect the visitors to know the product’s exact name when they search.
Bricks currently treats the Filter - Search input as the search phrase. It does not split “Big Button” into separate keywords or run fuzzy matching against “Big Red Button” out of the box.
There is already a related feature request topic for fuzzy/less-exact matching (though it hasn’t gained much traction so far) you already replied to
Thank you. Is there any way we can implement this functionality? Is there any hook I can poke somehow to make this work? A webshop or even any site with proper search functionality is bad for the site owners and the visitors too because if they don’t find the desired result they will leave.
Nice approach, and the fallback idea makes sense. However, I would tighten the snippet a bit before using it in production.
The main thing I’d avoid is replacing posts_search globally for every frontend/AJAX search. It is safer to mark only this specific fallback query and then only adjust the SQL for that query. I’d also use $wpdb->prepare(), split by any whitespace, and keep WordPress’ password-protected post condition for logged-out visitors.
Something like this should be safer (untested):
add_filter( 'bricks/query_filters/filter_query_vars', function( $query_vars, $filter, $query_id, $index ) {
if ( ( $filter['instance_name'] ?? '' ) !== 'filter-search' ) {
return $query_vars;
}
$search_value = trim( (string) ( $filter['value'] ?? '' ) );
if ( $search_value === '' ) {
return $query_vars;
}
// If Bricks custom search returned no IDs, fall back to native WP search.
if ( isset( $query_vars['post__in'] ) && $query_vars['post__in'] === [ 0 ] ) {
unset( $query_vars['post__in'] );
$query_vars['s'] = $search_value;
$query_vars['orderby'] = 'relevance';
$query_vars['brx_smart_search'] = true;
}
return $query_vars;
}, 20, 4 );
add_filter( 'posts_search', function( $search, $wp_query ) {
global $wpdb;
if ( ! $wp_query->get( 'brx_smart_search' ) ) {
return $search;
}
$search_terms = trim( (string) $wp_query->get( 's' ) );
if ( $search_terms === '' ) {
return $search;
}
$terms = preg_split( '/\s+/', $search_terms, -1, PREG_SPLIT_NO_EMPTY );
if ( count( $terms ) < 2 ) {
return $search;
}
$parts = [];
foreach ( $terms as $term ) {
$like = '%' . $wpdb->esc_like( $term ) . '%';
$parts[] = $wpdb->prepare(
"({$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_content LIKE %s OR {$wpdb->posts}.post_excerpt LIKE %s)",
$like,
$like,
$like
);
}
$search = ' AND ' . implode( ' AND ', $parts );
if ( ! is_user_logged_in() ) {
$search .= " AND ({$wpdb->posts}.post_password = '')";
}
return $search;
}, 500, 2 );