質問: $wpdb->prepare($sql,$source_lat,$source_lat,$source_lng); return $wpdb->get_results($sql); } 私の懸念は、sqlはあなたが得ることができるのと同じくらい最適化されていないということです。 ソースgeoは変更可能であり、キャッシュするためのソースgeosの有限セットはないため、mysqlは利用可能なインデックスで並べ替えることができません。現在、私はそれを最適化する方法について困惑しています。私がすでに行ったことを考慮に入れると、問題は次のとおりです。このユースケースの最適化についてどう思いますか?より良い解決策が私にそれを捨てさせてくれるなら私が私がしたことを何でも保つことは重要ではありません。 私はsphinxサーバーのインストールのような何かをすることを必要とするもの、あるいはカスタマイズされたmysql設定を必要とするものを除いて、ほとんどすべての解決策を検討することができます。基本的には、このソリューションは、単純なvanilla wordpressインストールで機能する必要があります。 (それは言った、誰かがより高度になることができるかもしれない他の人のためにそして後世のために代替解決策をリストしたいと思うなら素晴らしいでしょう。)見つかったリソースちなみに、私はこれについて少し研究をしました、それであなたは再び研究をしてもらうよりもむしろ私が先に行ってそれらを含める答えとしてこれらのリンクのいずれかを投稿してもらうのではありません。 http://jebaird.com/blog/calculating-distance-miles-latitude-and-longitude http://wordpress.org/extend/plugins/geolocation/screenshots/ http://code.google.com/apis/maps/articles/phpsqlsearch.html http://www.rooftopsolutions.nl/blog/229 http://planet.mysql.com/entry/?id=18085 http://blog.peoplesdns.com/archives/24 http://www.petefreitag.com/item/622.cfm http://www.phpro.org/tutorials/geo-targetting-with-php-and-mysql.html http://forum.geonames.org/gforum/posts/list/692.page http://forums.mysql.com/list.php?2 http://www.scribd.com/doc/2569355/geo-distance-search-with-mysql http://developer.yahoo.com/maps/rest/v1/geocode.html http://geocoder.us/ スフィンクス検索について http://sphinxsearch.com/ https://launchpad.net/wp-sphinx-plugin http://forums.site5.com/showthread.php?t=28981 http://wordpress.org/extend/plugins/wordpress-sphinx-plugin/ http://wordpress.org/extend/plugins/sphinx-search/ http://www.mysqlperformanceblog.com/2008/02/15/mysql-performance-blog-now-uses-sphinx-for-site-search/
回答: これはあなたには遅すぎるかもしれませんが、私はとにかく返事をするつもりです。 この関連質問に答えたのと同じように なので、将来の訪問者は両方の質問を参照できます。これらの値をpostメタデータテーブルに格納することはしません。少なくとも only は使用しません。 post_id、lat、lonの各列を含むテーブルが必要なので、lat, lonのインデックスを配置して、それにクエリを実行できます。これはポストセーブとアップデートのフックで最新の状態に保つのはそれほど難しくないはずです。データベースを照会するときは、開始点の周囲に 境界ボックス を定義するので、ボックスの南北と東西の境界の間のすべてのlat, lonペアに対して効率的な照会を実行できます。この結果が小さくなったら、より高度な(円周方向または実際の運転方向)距離計算を行って、境界ボックスの隅にある場所を除外し、目的以上に遠くに移動することができます。これが管理領域で機能する簡単なコード例です。追加のデータベーステーブルを自分で作成する必要があります。コードは、おもしろいものから順に並べられています。<?php /* plugin name: monkeyman geo test plugin uri: http://www.monkeyman.be description: geolocation test version: 1.0 author: jan fabry */ class monkeyman_geo { public function __construct() { add_action('init', array(&$this, 'registerposttype')); add_action('save_post', array(&$this, 'savelatlon'), 10, 2); add_action('admin_menu', array(&$this, 'addadminpages')); } /** * on post save, save the metadata in our special table * (post_id int, lat decimal(10,5), lon decimal (10,5)) * index on lat, lon */ public function savelatlon($post_id, $post) { if ($post->post_type != 'monkeyman_geo') { return; } $lat = floatval(get_post_meta($post_id, 'lat', true)); $lon = floatval(get_post_meta($post_id, 'lon', true)); global $wpdb; $result = $wpdb->replace( $wpdb->prefix . 'monkeyman_geo', array( 'post_id' => $post_id, 'lat' => $lat, 'lon' => $lon, ), array('%s', '%f', '%f') ); } public function addadminpages() { add_management_page( 'quick location generator', 'quick generator', 'edit_posts', __file__ . 'generator', array($this, 'dogeneratorpage')); add_management_page( 'location test', 'location test', 'edit_posts', __file__ . 'test', array($this, 'dotestpage')); } /** * simple test page with a location and a distance */ public function dotestpage() { if (!array_key_exists('search', $_request)) { $default_lat = ini_get('date.default_latitude'); $default_lon = ini_get('date.default_longitude'); echo <<<eof <form action="" method="post"> <p>center latitude: <input size="10" name="center_lat" value="{$default_lat}"/> <br/>center longitude: <input size="10" name="center_lon" value="{$default_lon}"/> <br/>max distance (km): <input size="5" name="max_distance" value="100"/></p> <p><input type="submit" name="search" value="search!"/></p> </form> eof; return; } $center_lon = floatval($_request['center_lon']); $center_lat = floatval($_request['center_lat']); $max_distance = floatval($_request['max_distance']); var_dump(self::getpostsuntildistancekm($center_lon, $center_lat, $max_distance)); } /** * get all posts that are closer than the given distance to the given location */ public static function getpostsuntildistancekm($center_lon, $center_lat, $max_distance) { list($north_lat, $east_lon, $south_lat, $west_lon) = self::getboundingbox($center_lat, $center_lon, $max_distance); $geo_posts = self::getpostsinboundingbox($north_lat, $east_lon, $south_lat, $west_lon); $close_posts = array(); foreach ($geo_posts as $geo_post) { $post_lat = floatval($geo_post->lat); $post_lon = floatval($geo_post->lon); $post_distance = self::calculatedistancekm($center_lat, $center_lon, $post_lat, $post_lon); if ($post_distance < $max_distance) { $close_posts[$geo_post->post_id] = $post_distance; } } return $close_posts; } /** * select all posts ids in a given bounding box */ public static function getpostsinboundingbox($north_lat, $east_lon, $south_lat, $west_lon) { global $wpdb; $sql = $wpdb->prepare('select post_id, lat, lon from ' . $wpdb->prefix . 'monkeyman_geo where lat < %f and lat > %f and lon < %f and lon > %f', array($north_lat, $south_lat, $west_lon, $east_lon)); return $wpdb->get_results($sql, object_k); } /* geographical calculations: distance and bounding box */ /** * calculate the distance between two coordinates * http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates/1416950#1416950 */ public static function calculatedistancekm($a_lat, $a_lon, $b_lat, $b_lon) { $d_lon = deg2rad($b_lon - $a_lon); $d_lat = deg2rad($b_lat - $a_lat); $a = pow(sin($d_lat/2.0), 2) + cos(deg2rad($a_lat)) * cos(deg2rad($b_lat)) * pow(sin($d_lon/2.0), 2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); $d = 6367 * $c; return $d; } /** * create a box around a given point that extends a certain distance in each direction * http://www.colorado.edu/geography/gcraft/warmup/aquifer/html/distance.html * * @todo: mind the gap at 180 degrees! */ public static function getboundingbox($center_lat, $center_lon, $distance_km) { $one_lat_deg_in_km = 111.321543; // fixed $one_lon_deg_in_km = cos(deg2rad($center_lat)) * 111.321543; // depends on latitude $north_lat = $center_lat + ($distance_km / $one_lat_deg_in_km); $south_lat = $center_lat - ($distance_km / $one_lat_deg_in_km); $east_lon = $center_lon - ($distance_km / $one_lon_deg_in_km); $west_lon = $center_lon + ($distance_km / $one_lon_deg_in_km); return array($north_lat, $east_lon, $south_lat, $west_lon); } /* below this it's not interesting anymore */ /** * generate some test data */ public function dogeneratorpage() { if (!array_key_exists('generate', $_request)) { $default_lat = ini_get('date.default_latitude'); $default_lon = ini_get('date.default_longitude'); echo <<<eof <form action="" method="post"> <p>number of posts: <input size="5" name="post_count" value="10"/></p> <p>center latitude: <input size="10" name="center_lat" value="{$default_lat}"/> <br/>center longitude: <input size="10" name="center_lon" value="{$default_lon}"/> <br/>max distance (km): <input size="5" name="max_distance" value="100"/></p> <p><input type="submit" name="generate" value="generate!"/></p> </form> eof; return; } $post_count = intval($_request['post_count']); $center_lon = floatval($_request['center_lon']); $center_lat = floatval($_request['center_lat']); $max_distance = floatval($_request['max_distance']); list($north_lat, $east_lon, $south_lat, $west_lon) = self::getboundingbox($center_lat, $center_lon, $max_distance); add_action('save_post', array(&$this, 'setpostlatlon'), 5); $precision = 100000; for ($p = 0; $p < $post_count; $p++) { self::$currentrandomlat = mt_rand($south_lat * $precision, $north_lat * $precision) / $precision; self::$currentrandomlon = mt_rand($west_lon * $precision, $east_lon * $precision) / $precision; $location = sprintf('(%f, %f)', self::$currentrandomlat, self::$currentrandomlon); $post_data = array( 'post_status' => 'publish', 'post_type' => 'monkeyman_geo', 'post_content' => 'point at ' . $location, 'post_title' => 'point at ' . $location, ); var_dump(wp_insert_post($post_data)); } } public static $currentrandomlat = null; public static $currentrandomlon = null; /** * because i didn't know how to save meta data with wp_insert_post, * i do it here */ public function setpostlatlon($post_id) { add_post_meta($post_id, 'lat', self::$currentrandomlat); add_post_meta($post_id, 'lon', self::$currentrandomlon); } /** * register a simple post type for us */ public function registerposttype() { register_post_type( 'monkeyman_geo', array( 'label' => 'geo location', 'labels' => array( 'name' => 'geo locations', 'singular_name' => 'geo location', 'add_new' => 'add new', 'add_new_item' => 'add new location', 'edit_item' => 'edit location', 'new_item' => 'new location', 'view_item' => 'view location', 'search_items' => 'search locations', 'not_found' => 'no locations found', 'not_found_in_trash' => 'no locations found in trash', 'parent_item_colon' => null, ), 'description' => 'geographical locations', 'public' => true, 'exclude_from_search' => false, 'publicly_queryable' => true, 'show_ui' => true, 'menu_position' => null, 'menu_icon' => null, 'capability_type' => 'post', 'capabilities' => array(), 'hierarchical' => false, 'supports' => array( 'title', 'editor', 'custom-fields', ), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'permalink_epmask' => ep_permalink, 'rewrite' => array( 'slug' => 'locations', ), 'query_var' => true, 'can_export' => true, 'show_in_nav_menus' => true, ) ); } } $monkeyman_geo_instance = new monkeyman_geo();