Index: src/wp-includes/query.php
===================================================================
--- src/wp-includes/query.php	(revision 27468)
+++ src/wp-includes/query.php	(working copy)
@@ -1973,15 +1973,40 @@
 			}
 		}
 
+		/**
+		 * Filter the fields used when searching for posts.
+		 *
+		 * By default, a search on the posts table will use post_title and
+		 * post_content. This filter is available to expand that search to
+		 * other applicable fields.
+		 *
+		 * Allowed fields are post_title, post_content, post_excerpt, post_name,
+		 * and post_content_filtered.
+		 *
+		 * @since 3.9.0
+		 *
+		 * @param array    $fields Fields from a list of allowed search fields.
+		 * @param WP_Query $this   The WP_Query instance.
+		 */
+		$fields = apply_filters( 'posts_search_fields', array( 'post_title', 'post_content' ), $this );
+		$allowed = array( 'post_title', 'post_content', 'post_excerpt', 'post_name', 'post_content_filtered' );
+		$fields = array_intersect( $fields, $allowed );
+
+		$conditions = array();
+		foreach( $fields as $field ) {
+			$conditions[] = "( $wpdb->posts.$field" . ' LIKE \'%1$s\')';
+		}
+		$conditions = join( ' OR ', $conditions );
+
 		$n = ! empty( $q['exact'] ) ? '' : '%';
 		$searchand = '';
 		$q['search_orderby_title'] = array();
 		foreach ( $q['search_terms'] as $term ) {
 			$term = like_escape( esc_sql( $term ) );
-			if ( $n )
+			if ( $n ) {
 				$q['search_orderby_title'][] = "$wpdb->posts.post_title LIKE '%$term%'";
-
-			$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
+			}
+			$search .= "{$searchand}(" . sprintf( $conditions, "{$n}{$term}{$n}" ) . ")";
 			$searchand = ' AND ';
 		}
 
Index: tests/phpunit/tests/query/search.php
===================================================================
--- tests/phpunit/tests/query/search.php	(revision 27474)
+++ tests/phpunit/tests/query/search.php	(working copy)
@@ -29,6 +29,9 @@
 		return $this->q->query( $args );
 	}
 
+	/**
+	 * @ticket 7394
+	 */
 	function test_search_order_title_relevance() {
 		foreach ( range( 1, 7 ) as $i )
 			$this->factory->post->create( array( 'post_content' => $i . rand_str() . ' about', 'post_type' => $this->post_type ) );
@@ -38,6 +41,9 @@
 		$this->assertEquals( $post_id, reset( $posts )->ID );
 	}
 
+	/**
+	 * @ticket 7394
+	 */
 	function test_search_terms_query_var() {
 		$terms = 'This is a search term';
 		$query = new WP_Query( array( 's' => 'This is a search term' ) );
@@ -45,6 +51,9 @@
 		$this->assertEquals( array( 'search', 'term' ), $query->get( 'search_terms' ) );
 	}
 
+	/**
+	 * @ticket 7394
+	 */
 	function test_filter_stopwords() {
 		$terms = 'This is a search term';
 		add_filter( 'wp_search_stopwords', array( $this, 'filter_wp_search_stopwords' ) );
@@ -58,4 +67,41 @@
 	function filter_wp_search_stopwords() {
 		return array();
 	}
+
+	/**
+	 * @ticket 20044
+	 */
+	function test_search_by_fields() {
+		$post_id = $this->factory->post->create( array( 'post_title' => 'Taco', 'post_name' => 'burrito', 'post_content' => 'Enchilada', 'post_excerpt' => 'Torta' ) );
+
+		// post title
+		$q1 = new WP_Query( array( 's' => 'taco', 'fields' => 'ids' ) );
+		$this->assertEquals( array( $post_id ), $q1->posts );
+
+		// post content
+		$q2 = new WP_Query( array( 's' => 'enchilada', 'fields' => 'ids' ) );
+		$this->assertEquals( array( $post_id ), $q2->posts );
+
+		// post slug
+		$q3 = new WP_Query( array( 's' => 'Burrito', 'fields' => 'ids' ) );
+		$this->assertEquals( array(), $q3->posts );
+
+		// post excerpt
+		$q4 = new WP_Query( array( 's' => 'Torta', 'fields' => 'ids' ) );
+		$this->assertEquals( array(), $q4->posts );
+
+		add_filter( 'query_search_fields', array( $this, 'filter_query_search_fields' ) );
+		$q5 = new WP_Query( array( 's' => 'Burrito', 'fields' => 'ids' ) );
+		$this->assertEquals( array( $post_id ), $q5->posts );
+
+		$q6 = new WP_Query( array( 's' => 'Torta', 'fields' => 'ids' ) );
+		$this->assertEquals( array( $post_id ), $q6->posts );
+		remove_filter( 'query_search_fields', array( $this, 'filter_query_search_fields' ) );
+	}
+
+	function filter_query_search_fields( $fields ) {
+		$fields[] = "post_name";
+		$fields[] = "post_excerpt";
+		return $fields;
+	}
 }
