feat: refact general search
This commit is contained in:
parent
310ca1ed02
commit
0b562f0797
|
@ -93,7 +93,8 @@ class REST_Controller extends \WP_REST_Controller {
|
|||
'hierarchical' => 'hierarchical',
|
||||
'exclude' => 'post__not_in',
|
||||
'excludetree' => 'exclude_tree',
|
||||
'include' => 'include'
|
||||
'include' => 'include',
|
||||
'sentence' => 'sentence'
|
||||
];
|
||||
|
||||
$meta_query = [
|
||||
|
@ -312,6 +313,12 @@ class REST_Controller extends \WP_REST_Controller {
|
|||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
$query_params['sentence'] = array(
|
||||
'description' => __( 'Whether to search by phrase. Default false.', 'tainacan' ),
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
);
|
||||
|
||||
$query_params['authorid'] = array(
|
||||
'description' => __("Limit result set to objects assigned to specific authors by id.", 'tainacan'),
|
||||
'type' => 'integer',
|
||||
|
|
|
@ -53,9 +53,21 @@ class Elastic_Press {
|
|||
//https://www.elasticpress.io/blog/2019/02/custom-search-with-elasticpress-how-to-limit-results-to-full-text-matches/
|
||||
if ( ! empty( $formatted_args['query']['bool']['should'] ) ) {
|
||||
$formatted_args['query']['bool']['must'] = $formatted_args['query']['bool']['should'];
|
||||
$formatted_args['query']['bool']['must'][0]['multi_match']['operator'] = 'AND';
|
||||
$formatted_args["query"]["bool"]["must"][0]["multi_match"]["type"] = "phrase_prefix";
|
||||
|
||||
// $formatted_args['query']['bool']['must'][0]['multi_match']['operator'] = 'AND';
|
||||
if ( isset($formatted_args['query']['bool']['must'][0]['multi_match']['operator']))
|
||||
unset($formatted_args['query']['bool']['must'][0]['multi_match']['operator']);
|
||||
if ( isset($formatted_args['query']['bool']['must'][1]['multi_match']['operator']))
|
||||
unset($formatted_args['query']['bool']['must'][1]['multi_match']['operator']);
|
||||
if ( isset($formatted_args['query']['bool']['must'][2]['multi_match']['operator']))
|
||||
unset($formatted_args['query']['bool']['must'][2]['multi_match']['operator']);
|
||||
|
||||
if ( isset($formatted_args['query']['bool']['must'][2]) ) {
|
||||
$formatted_args['query']['bool']['must'][2]['multi_match']['analyzer'] = 'default';
|
||||
}
|
||||
|
||||
unset( $formatted_args['query']['bool']['should'] );
|
||||
unset( $formatted_args["query"]["bool"]["must"][0]["multi_match"]["type"] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,22 +75,22 @@ class Elastic_Press {
|
|||
* Elasticsearch is not good a substring matches similar to SQL like.
|
||||
* here we replace `match_phrase` with` wildcard`, but this is not an efficient operation.
|
||||
*/
|
||||
if ( ! empty( $formatted_args['post_filter']['bool']['must'] ) ) {
|
||||
$array_must = $formatted_args['post_filter']['bool']['must'];
|
||||
for($i = 0; $i < count($array_must); $i++ ) {
|
||||
$el_must = $array_must[$i];
|
||||
if( ! empty($el_must['bool']['must']) ) {
|
||||
$array_must_nested = $el_must['bool']['must'];
|
||||
for($j = 0; $j < count($array_must_nested); $j++ ) {
|
||||
if ( isset ($array_must_nested[$j]['match_phrase'] ) ) {
|
||||
$formatted_args['post_filter']['bool']['must'][$i]['bool']['must'][$j]['match_phrase_prefix'] =
|
||||
array_map( function($match) { return "$match"; } ,$array_must_nested[$j]['match_phrase']);
|
||||
unset($formatted_args['post_filter']['bool']['must'][$i]['bool']['must'][$j]['match_phrase']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if ( ! empty( $formatted_args['post_filter']['bool']['must'] ) ) {
|
||||
// $array_must = $formatted_args['post_filter']['bool']['must'];
|
||||
// for($i = 0; $i < count($array_must); $i++ ) {
|
||||
// $el_must = $array_must[$i];
|
||||
// if( ! empty($el_must['bool']['must']) ) {
|
||||
// $array_must_nested = $el_must['bool']['must'];
|
||||
// for($j = 0; $j < count($array_must_nested); $j++ ) {
|
||||
// if ( isset ($array_must_nested[$j]['match_phrase'] ) ) {
|
||||
// $formatted_args['post_filter']['bool']['must'][$i]['bool']['must'][$j]['match_phrase_prefix'] =
|
||||
// array_map( function($match) { return "$match"; } ,$array_must_nested[$j]['match_phrase']);
|
||||
// unset($formatted_args['post_filter']['bool']['must'][$i]['bool']['must'][$j]['match_phrase']);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return $formatted_args;
|
||||
} );
|
||||
|
|
|
@ -60,7 +60,7 @@ class Search_Engine {
|
|||
// added slashes screw with quote grouping when done early, so done later
|
||||
$s = stripslashes( $s );
|
||||
if ( $sentence ) {
|
||||
$search_terms = array( $s );
|
||||
$search_terms = array( trim($s, " '\"\n\r\t\v\0") );
|
||||
} else {
|
||||
preg_match_all( '/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $s, $matches );
|
||||
|
||||
|
@ -116,7 +116,7 @@ class Search_Engine {
|
|||
}
|
||||
}
|
||||
|
||||
private function build_search_terms_query ($type = 'default') {
|
||||
function get_where_to_title_and_content() {
|
||||
global $wpdb;
|
||||
$searchQuery = '';
|
||||
$seperator = '';
|
||||
|
@ -124,62 +124,68 @@ class Search_Engine {
|
|||
$terms = $this->get_search_terms();
|
||||
foreach ( $terms as $term ) {
|
||||
$esc_term = $wpdb->prepare("%s", $not_exact ? "%".$term."%" : $term);
|
||||
switch ($type) {
|
||||
case 'tax_terms':
|
||||
$searchQuery .= "{$seperator}(tter.name LIKE {$esc_term})";
|
||||
break;
|
||||
case 'meta_terms':
|
||||
if (defined('TAINACAN_SEARCH_ENGINE_USING_FULL_TEXT') && TAINACAN_SEARCH_ENGINE_USING_FULL_TEXT === true) {
|
||||
$esc_term = $wpdb->prepare("%s", $not_exact ? "*".$term."*" : $term);
|
||||
$searchQuery .= "{$seperator}(MATCH (m.meta_value) AGAINST ({$esc_term} IN BOOLEAN MODE))";
|
||||
} else {
|
||||
$searchQuery .= "{$seperator}(m.meta_value LIKE {$esc_term})";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ( !empty( $this->relationships ) ) {
|
||||
$searchQuery .= "{$seperator}($wpdb->posts.post_title LIKE {$esc_term} OR $wpdb->posts.post_content LIKE {$esc_term} OR p2->posts.post_title LIKE {$esc_term} OR p2.post_content LIKE {$esc_term})";
|
||||
} else {
|
||||
$searchQuery .= "{$seperator}($wpdb->posts.post_title LIKE {$esc_term} OR $wpdb->posts.post_content LIKE {$esc_term})";
|
||||
}
|
||||
break;
|
||||
}
|
||||
$seperator = ' OR ';
|
||||
$seperator = ' AND ';
|
||||
}
|
||||
return empty($searchQuery) ? false : "($searchQuery)";
|
||||
}
|
||||
|
||||
function get_where_to_term_taxonomies() {
|
||||
if ( $this->is_tainacan_search && !empty( $this->taxonomies ) ) {
|
||||
global $wpdb;
|
||||
$join = '';
|
||||
$searchTaxQuery = $this->build_search_terms_query('tax_terms');
|
||||
if ( $searchTaxQuery != false && $this->is_tainacan_search && !empty( $this->taxonomies ) ) {
|
||||
$search_tax_query = '';
|
||||
$seperator = '';
|
||||
$not_exact = empty($this->query_instance->query_vars['exact']);
|
||||
$terms = $this->get_search_terms();
|
||||
foreach ( $terms as $term ) {
|
||||
$esc_term = $wpdb->prepare("%s", $not_exact ? "%".$term."%" : $term);
|
||||
$search_tax_query .= "{$seperator}(tter.name LIKE {$esc_term})";
|
||||
$seperator = ' AND ';
|
||||
}
|
||||
if (empty($search_tax_query)) return '';
|
||||
|
||||
$tax_where = ' ttax.taxonomy IN ( \'' . implode( '\',\'', $this->taxonomies ) . '\' ) ';
|
||||
$join = "EXISTS (
|
||||
return "EXISTS (
|
||||
SELECT trel.object_id
|
||||
FROM
|
||||
$wpdb->term_relationships AS trel
|
||||
INNER JOIN $wpdb->term_taxonomy AS ttax ON trel.term_taxonomy_id = ttax.term_taxonomy_id
|
||||
INNER JOIN $wpdb->terms AS tter ON ttax.term_id = tter.term_id
|
||||
WHERE
|
||||
$wpdb->posts.ID = trel.object_id AND $tax_where AND ( $searchTaxQuery )
|
||||
$wpdb->posts.ID = trel.object_id AND $tax_where AND ( $search_tax_query )
|
||||
)";
|
||||
}
|
||||
return $join;
|
||||
return '';
|
||||
}
|
||||
|
||||
function get_where_to_metadatas() {
|
||||
if ( $this->is_tainacan_search ) {
|
||||
global $wpdb;
|
||||
$join = "";
|
||||
$searchMetaQuery = $this->build_search_terms_query('meta_terms');
|
||||
if ( $searchMetaQuery != false && $this->is_tainacan_search ) {
|
||||
$join .= "EXISTS (
|
||||
$search_meta_query = '';
|
||||
$seperator = '';
|
||||
$not_exact = empty($this->query_instance->query_vars['exact']);
|
||||
$terms = $this->get_search_terms();
|
||||
foreach ( $terms as $term ) {
|
||||
$esc_term = $wpdb->prepare("%s", $not_exact ? "%".$term."%" : $term);
|
||||
$search_meta_query .= "{$seperator}(m.meta_value LIKE {$esc_term})";
|
||||
$seperator = ' AND ';
|
||||
}
|
||||
if ( empty($search_meta_query) ) return '';
|
||||
|
||||
$join = \is_user_logged_in()
|
||||
? ''
|
||||
: " INNER JOIN $wpdb->posts pmeta ON m.meta_key = pmeta.ID AND pmeta.post_status = 'publish'";
|
||||
return "EXISTS (
|
||||
SELECT m.post_id
|
||||
FROM $wpdb->postmeta m
|
||||
WHERE ( $wpdb->posts.ID = m.post_id AND $searchMetaQuery )
|
||||
FROM $wpdb->postmeta m $join
|
||||
WHERE ( $wpdb->posts.ID = m.post_id AND $search_meta_query )
|
||||
)";
|
||||
}
|
||||
return $join;
|
||||
return '';
|
||||
}
|
||||
|
||||
// add where clause to the search query
|
||||
|
@ -195,16 +201,16 @@ class Search_Engine {
|
|||
if ( !$this->is_tainacan_search && !$this->ajax_request)
|
||||
return $where;
|
||||
|
||||
$searchQuery = $this->build_search_terms_query();
|
||||
$searchTaxQuery = $this->get_where_to_term_taxonomies();
|
||||
$searchMetaQuery = $this->get_where_to_metadatas();
|
||||
$searchQuery = "($searchQuery) ";
|
||||
if(!empty($searchTaxQuery)) $searchQuery .= " OR ($searchTaxQuery) ";
|
||||
if(!empty($searchMetaQuery)) $searchQuery .= " OR ($searchMetaQuery) ";
|
||||
$search_query = $this->get_where_to_title_and_content();
|
||||
$search_tax_query = $this->get_where_to_term_taxonomies();
|
||||
$search_meta_query = $this->get_where_to_metadatas();
|
||||
$search_query = "($search_query) ";
|
||||
if(!empty($search_tax_query)) $search_query .= " OR ($search_tax_query) ";
|
||||
if(!empty($search_meta_query)) $search_query .= " OR ($search_meta_query) ";
|
||||
|
||||
if ( $searchQuery != '' && $searchQuery != '()' ) {
|
||||
if ( $search_query != '' && $search_query != '()' ) {
|
||||
// lets use _OUR_ query instead of WP's, as we have posts already included in our query as well(assuming it's not empty which we check for)
|
||||
$where = " AND ((" . $searchQuery . ")) ";
|
||||
$where = " AND ((" . $search_query . ")) ";
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue