Make WordPress Core

Opened 4 years ago

Last modified 4 years ago

#43867 new feature request

Introduce the ability to control which fields are searched in a search query

Reported by: johnbillion Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Query Keywords: has-patch has-unit-tests
Focuses: Cc:


The s argument of the WP_Query::parse_query() method always searches the post_title, post_excerpt, and post_content fields, with no way of controlling this apart from using the posts_search filter and adjusting the SQL manually.

It would be good if it was possible to specify which fields are searched when performing a query, for example via a search_fields argument or similar.

My use case is for a REST API driven autocomplete field which allows a user to search post titles without a large number of less relevant results appearing due to the search spanning post content too.

Attachments (1)

43867.diff (15.2 KB) - added by birgire 4 years ago.

Download all attachments as: .zip

Change History (5)

#1 @birgire
4 years ago

That sounds like a useful feature.

For comparison, the way it's done in WP_User_Query is with the search_columns query argument:


and also the user_search_columns filter:


where the default search fields are (marked with x):

x ID
x user_login
x user_nicename
x user_email
x user_url
x display_name

Similar the WP_Site_Query uses the search_columns query argument:


and the site_search_columns filter, with the default search columns:

x domain
x path 


So taking a similar approach as above, we could support:

  • the search_columns query argument
  • and the post_search_columns or search_columns filter.

with the default columns as:

x post_title
x post_excerpt
x post_content

Version 5, edited 4 years ago by birgire (previous) (next) (diff)

#2 @birgire
4 years ago

The parse_search() seems like a good place for
the filter:

$search_columns = apply_filters( 'post_search_columns', $search_columns, $q['s'], $this );

where we can loop over the columns with e.g.:

$searches = array(); 
foreach( (array) $search_columns as $search_column ) {
	$searches[] = $wpdb->prepare( "({$wpdb->posts}.{$search_column} $like_op %s)", $like ); 

if( $searches ) {
	$search .= "{$searchand}(" . join( " $andor_op", $searches ) . ')';

within the search terms loop.

I will look into this further with unit tests.

4 years ago

#3 @birgire
4 years ago

43867.diff is a first iteration with unit tests in tests/query/searchColumns.php.

Some notes on this first iteration:

  • It uses the default search columns: post_title, post_excerpt and post_content.
  • It uses the supported search columns: post_title, post_excerpt and post_content. We could consider expanding this further.
  • It uses the default search columns as a fallback for empty input: 'search_columns' => array().
  • It uses the default search columns as a fallback for an existing but not supported search field, e.g. 'search_columns' => array( 'post_name' ).
  • It ignores non-existing or non supported search column(s) together with supported search column(s), e.g. 'search_columns' => array( 'post_title', 'post_name' ) is the same as 'search_columns' => array( 'post_title' ).
  • Introduces the post_search_columns filter. We restrict it to the supported search columns, to avoid any kind of column names in the SQL query.

#4 @birgire
4 years ago

  • Keywords has-patch has-unit-tests added; needs-patch needs-unit-tests removed
Note: See TracTickets for help on using tickets.