Ich habe eine mySQL-Abfrage, um eine ziemlich komplizierte Suche in WordPress zu handhaben, weil ich Schwierigkeiten hatte, sie zu bekommen wp_query
um alles zu tun, was ich brauche.
Manchmal dauert die Ausführung der Abfrage jedoch sehr lange (manchmal über 10 Sekunden!) internal server error
oder ein Error establishing database connection
.
Ich bin mir nicht sicher, ob es einen allgemeinen Syntaxfehler in der Abfrage gibt, der zum Absturz führt oder nicht, aber im Wesentlichen sieht das PHP, das die Abfrage generiert, so aus:
<?php
// declare wordpress database global
global $wpdb;
// order by option
$order = $_SESSION['search']['sort-by'];
// users lat, long and distance preferences
$lat = $_SESSION['search']['lat'];
$long = $_SESSION['search']['long'];
$radius = $_SESSION['search']['distance'];
// user search start/end date
$startDate = date('Ymd', strtotime($_SESSION['search']['from']));
$endDate = date('Ymd', strtotime($_SESSION['search']['to']));
// get the main category search ID
$maincat = get_term_by( 'slug', $_SESSION['search']['cat'], 'main-cat');
$maincat = $maincat->term_taxonomy_id;
// grab keywords, replace special chars and spaces
$keywords = $_SESSION['search']['keyword'];
$keywords = preg_replace('/[^A-Za-z0-9 ,]/u','', strip_tags($keywords));
$keywords = str_replace(' ', '', $keywords);
// put keywords into array
$subcatItems = explode(',', $keywords);
$keywords = $subcatItems;
// for each keywords get the sub category id's
$subcats = array();
$count = count($subcatItems) - 2;
for ($i = 0; $i <= $count; $i++) {
$subcatItems[$i] = get_term_by( 'slug', $subcatItems[$i], 'sub-cat');
if ($subcatItems[$i] != '') :
$subcatItems[$i] = $subcatItems[$i]->term_taxonomy_id;
array_push($subcats, $subcatItems[$i]);
endif;
}
if( $subcats != '' ) :
$subcats = implode(',', $subcats);
endif;
// select
$query = 'SELECT SQL_CALC_FOUND_ROWS wp_posts.*, ';
// geo locate
$query .= '( 3959 * acos(
cos( radians('.$lat.') )
* cos( radians( lat ) )
* cos( radians( lng ) - radians('.$long.') )
+ sin( radians('.$lat.') )
* sin( radians( lat ) )
) )
AS distance , lat AS latitude , lng AS longitude ';
// from
$query .= 'FROM wp_posts ';
// inner joins
$query .= 'INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) ';
if ( $keywords != '' ) :
$query .= 'INNER JOIN wp_term_relationships AS tt1 ON (wp_posts.ID = tt1.object_id) ';
endif;
$query .= 'INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) ';
$query .= 'INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) ';
// if ordered by price, join post meta again
if( $order == 'mt2.meta_value+0' ) :
$query .= 'INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) ';
endif;
// if there are keywords
if ( $keywords != '' ) :
$query .= 'INNER JOIN wp_postmeta AS mt3 ON (wp_posts.ID = mt3.post_id) ';
endif;
// join table to geo locate
$query .= 'INNER JOIN lat_lng_post ON wp_posts.ID = lat_lng_post.post_id ';
// basic filter
$query .= 'WHERE 1=1 ';
$query .= 'AND wp_posts.post_type = "event" ';
$query .= 'AND wp_posts.post_status = "publish" ';
// geo filter
$query .= 'AND lat_lng_post.lat = lat ';
$query .= 'AND lat_lng_post.lng = lng ';
// date filter
$query .= 'AND ( ';
$query .= '(wp_postmeta.meta_key LIKE "date_%_start-date" AND CAST(wp_postmeta.meta_value AS SIGNED) <= "'.$endDate.'") ';
$query .= 'AND (mt1.meta_key LIKE "date_%_end-date" AND CAST(mt1.meta_value AS SIGNED) >= "'.$startDate.'") ';
$query .= 'AND substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6) ';
$query .= ') ';
// taxonomies filter
$query .= 'AND ( wp_term_relationships.term_taxonomy_id IN ('.$maincat.') ) ';
// if keywords
if ( $_SESSION['search']['keyword'] != '' ) :
$query .= 'AND ( ';
// for each keyword, and a statement to check post title
$keywordCount = 0;
foreach ( $keywords as $keyword ) :
if( $keyword != '' ) :
if( $keywordCount == 0 ) :
$query .= '(wp_posts.post_title LIKE "%'.$keyword.'%") ';
else :
$query .= 'OR (wp_posts.post_title LIKE "%'.$keyword.'%") ';
endif;
endif;
$keywordCount++;
endforeach;
// for each keyword, and a statement to check description
foreach ( $keywords as $keyword ) :
if( $keyword != '' ) :
$query .= 'OR (mt3.meta_key = "description" AND mt3.meta_value LIKE "%'.$keyword.'%") ';
endif;
endforeach;
// for each keyword, and a statement to check sub category taxonomy
if( $subcats != '' ) :
$query .= 'OR ( tt1.term_taxonomy_id IN ('.$subcats.') )';
endif;
$query .= ') ';
endif;
// if ordered by adult
if( $order == 'mt2.meta_value+0' ) :
$query .= 'AND mt2.meta_key = "adult" ';
endif;
// grouping and sorting
$query .= 'GROUP BY wp_posts.ID ';
$query .= 'HAVING distance <= '.$radius.' ';
$query .= 'ORDER BY '.$order.' ASC ';
$query .= 'LIMIT 0, 10';
$events = $wpdb->get_results( $query, 'OBJECT' );
?>
Wenn jemand eine Idee hat, bitte melden! Und wenn ihr noch mehr Infos braucht, liefere ich sie gerne 🙂
BEARBEITEN
Die Abfrage scheint viel mehr Probleme zu haben, wenn Schlüsselwörter in der Suche vorhanden sind. Ich bin mir nicht sicher, ob es einen besseren Weg gibt, die Logik zu schreiben:
if ( $_SESSION['search']['keyword'] != '' ) :
$query .= 'AND ( ';
// for each keyword, and a statement to check post title
$keywordCount = 0;
foreach ( $keywords as $keyword ) :
if( $keyword != '' ) :
if( $keywordCount == 0 ) :
$query .= '(wp_posts.post_title LIKE "%'.$keyword.'%") ';
else :
$query .= 'OR (wp_posts.post_title LIKE "%'.$keyword.'%") ';
endif;
endif;
$keywordCount++;
endforeach;
// for each keyword, and a statement to check description
foreach ( $keywords as $keyword ) :
if( $keyword != '' ) :
$query .= 'OR (mt3.meta_key = "description" AND mt3.meta_value LIKE "%'.$keyword.'%") ';
endif;
endforeach;
// for each keyword, and a statement to check sub category taxonomy
if( $subcats != '' ) :
$query .= 'OR ( tt1.term_taxonomy_id IN ('.$subcats.') )';
endif;
$query .= ') ';
endif;
BEARBEITEN 2
Ein weiterer Gedanke, den ich gerade hatte, wäre es vielleicht schneller, die Abfrage in separate Abfragen aufzuteilen? Vervollständigen Sie also zuerst die Geo-Abfrage, nehmen Sie diese Post-IDs und führen Sie die Datumsabfrage durch. Führen Sie dann vielleicht die Schlüsselwortabfrage durch? Ich bin ziemlich neu in mySQL, also nicht sicher, wie ich das optimieren soll :/
Nun, es ist eine wirklich schwere Abfrage. Vielleicht würde das Verschieben der Entfernungsberechnung aus MySQL helfen.
– Pinoniq
4. Juli 2014 um 8:35 Uhr
Ist es möglich, dies aus mySQL zu verschieben? Alle zu prüfenden Breiten- und Längengrade sind in der Datenbank gespeichert :/
– Lukas
4. Juli 2014 um 8:36 Uhr
Hast du dir das langsame Abfrageprotokoll des MySQL-Servers angesehen? Um einen allgemeinen SQL-Syntaxfehler auszuschließen, könnten Sie die generierte Abfrage kurz vor dem Aufruf von an eine Protokolldatei anhängen
$events = $wpdb->get_results( $query, 'OBJECT' );
. Mit Hilfe dieses Protokolls könnten Sie es mit Hilfe von versuchenEXPLAIN
um die Abfrage zu optimieren.– VMai
4. Juli 2014 um 9:05 Uhr
Ich habe mir das nicht wirklich angesehen, ich habe zuvor versucht, EXPLAIN zur Abfrage hinzuzufügen, aber es wird nie ausgeführt, ich bin mir nicht sicher, ob es etwas mit $wpdb zu tun hat? Das gibt Syntaxfehler für mySQL, also würde ich mir vorstellen, dass sie dort auftauchen würden, um ehrlich zu sein?
– Lukas
4. Juli 2014 um 9:50 Uhr