मैं वर्डप्रेस में स्थान आधारित (ज़िप कोड) खोज को कैसे लागू कर सकता हूं?


19

मैं एक स्थानीय व्यापार निर्देशिका साइट पर काम कर रहा हूं जो व्यावसायिक प्रविष्टियों के लिए कस्टम पोस्ट प्रकारों का उपयोग करेगी। खेतों में से एक "ज़िप कोड" होगा। मैं स्थान आधारित खोज कैसे सेट कर सकता हूं?

मैं चाहूंगा कि आगंतुक अपने ज़िप कोड को दर्ज करने में सक्षम हों और एक श्रेणी चुनें और एक निश्चित त्रिज्या वाले सभी व्यवसायों को दिखाएं, या दूरी द्वारा आदेशित सभी व्यवसाय। मैंने एक दो प्लगइन्स देखे जो ऐसा करने का दावा करते हैं लेकिन वे वर्डप्रेस 3.0 का समर्थन नहीं करते हैं। कोई सुझाव?


2
मैं एक इनाम शुरू कर रहा हूं क्योंकि यह एक दिलचस्प और चुनौतीपूर्ण सवाल है। मेरे पास अपने खुद के कुछ विचार हैं ... लेकिन मैं देखना चाहता हूं कि क्या कोई और अधिक सुरुचिपूर्ण (और निर्माण करने में आसान) के साथ आ सकता है।
14

धन्यवाद एमान यह मदद कर सकता है: briancray.com/2009/04/01/…
मैट

केवल सुझाव है कि मैं वर्तमान में यहाँ एक प्लग जैसे फली का उपयोग करने के लिए है
NetConstructor.com

@ NetConstructor.com - मैं इसके लिए पॉड्स का सुझाव नहीं दूंगा ; वास्तव में कोई लाभ नहीं है पोड्स यह समस्या बनाम कस्टम पोस्ट प्रकार प्रदान करता है।
माइकस्किंकल

@matt : मैंने हाल ही में इस पर कुछ समान लागू किया है, हालांकि साइट को अंतिम रूप नहीं दिया गया है और न ही अभी तक तैनात किया गया है। वास्तव में यह थोड़ा बहुत है। मैं इसे किसी बिंदु पर एक स्टोर लोकेटर प्लगइन के रूप में पैकेज करने की योजना बना रहा हूं, लेकिन यह कुछ ऐसा नहीं है जिसे मैं अभी तक एक सामान्य समाधान के रूप में पोस्ट कर सकता हूं। मुझसे ऑफ़लाइन संपर्क करें और यदि आपको आवश्यक उत्तर नहीं मिला तो मैं मदद कर सकता हूं।
माइकस्किंकल

जवाबों:


10

मैं डेटाबेस अनुक्रमित का उपयोग करके और वास्तविक दूरी की गणना की संख्या को कम करके गैब्रिएलक और लिंक किए गए ब्लॉग पोस्ट से उत्तर को संशोधित करूंगा

यदि आप उपयोगकर्ता के निर्देशांक जानते हैं और आप अधिकतम दूरी जानते हैं (10 किमी कहते हैं), तो आप एक बाउंडिंग बॉक्स खींच सकते हैं जो कि 20 किमी तक 20 किमी है और बीच में वर्तमान स्थान है। इन अक्षांश निर्देशांक और अनुदैर्ध्य के बीच केवल बाउंडिंग निर्देशांक और क्वेरी प्राप्त करें । अभी तक अपने डेटाबेस क्वेरी में त्रिकोणमिति फ़ंक्शंस का उपयोग न करें, क्योंकि यह अनुक्रमित को उपयोग करने से रोक देगा। (तो आपको एक स्टोर मिल सकता है जो कि आपसे 12 किमी दूर है अगर यह बाउंडिंग बॉक्स के उत्तर-पूर्वी कोने में है, लेकिन हम इसे अगले चरण में फेंक देते हैं।)

केवल कुछ दुकानों के लिए दूरी (जैसे कि पक्षी उड़ता है या वास्तविक ड्राइविंग दिशाओं के साथ, आप पसंद करते हैं) वापस आ जाते हैं। यदि आपके पास बड़ी संख्या में स्टोर हैं, तो यह प्रसंस्करण समय में काफी सुधार करेगा।

संबंधित लुकअप के लिए ( "दस निकटतम स्टोर दें" ) आप एक समान लुकअप कर सकते हैं, लेकिन एक प्रारंभिक दूरी के अनुमान के साथ (इसलिए आप 10 किमी 10 किमी क्षेत्र से शुरू करते हैं, और यदि आपके पास पर्याप्त स्टोर नहीं हैं तो आप इसका विस्तार कर सकते हैं। 20 किमी 20 किमी और इतने पर)। इस प्रारंभिक दूरी के अनुमान के लिए, आप एक बार कुल क्षेत्र में दुकानों की संख्या की गणना करते हैं और इसका उपयोग करते हैं। या आवश्यक प्रश्नों की संख्या लॉग करें और समय के साथ अनुकूलित करें।

मैंने माइक से संबंधित प्रश्न में एक पूर्ण कोड उदाहरण जोड़ा , और यहां एक एक्सटेंशन दिया गया है जो आपको निकटतम एक्स स्थान देता है (त्वरित और मुश्किल से परीक्षण किया गया):

class Monkeyman_Geo_ClosestX extends Monkeyman_Geo
{
    public static $closestXStartDistanceKm = 10;
    public static $closestXMaxDistanceKm = 1000; // Don't search beyond this

    public function addAdminPages()
    {
        parent::addAdminPages();
        add_management_page( 'Location closest test', 'Location closest test', 'edit_posts', __FILE__ . 'closesttest', array(&$this, 'doClosestTestPage'));
    }

    public function doClosestTestPage()
    {
        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>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}"/></p>
    <p><input type="submit" name="search" value="Search!"/></p>
</form>
EOF;
            return;
        }
        $post_count = intval($_REQUEST['post_count']);
        $center_lon = floatval($_REQUEST['center_lon']);
        $center_lat = floatval($_REQUEST['center_lat']);

        var_dump(self::getClosestXPosts($center_lon, $center_lat, $post_count));
    }

    /**
     * Get the closest X posts to a given location
     *
     * This might return more than X results, and never more than
     * self::$closestXMaxDistanceKm away (to prevent endless searching)
     * The results are sorted by distance
     *
     * The algorithm starts with all locations no further than
     * self::$closestXStartDistanceKm, and then grows this area
     * (by doubling the distance) until enough matches are found.
     *
     * The number of expensive calculations should be minimized.
     */
    public static function getClosestXPosts($center_lon, $center_lat, $post_count)
    {
        $search_distance = self::$closestXStartDistanceKm;
        $close_posts = array();
        while (count($close_posts) < $post_count && $search_distance < self::$closestXMaxDistanceKm) {
            list($north_lat, $east_lon, $south_lat, $west_lon) = self::getBoundingBox($center_lat, $center_lon, $search_distance);

            $geo_posts = self::getPostsInBoundingBox($north_lat, $east_lon, $south_lat, $west_lon);


            foreach ($geo_posts as $geo_post) {
                if (array_key_exists($geo_post->post_id, $close_posts)) {
                    continue;
                }
                $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 < $search_distance) {
                    // Only include those that are in the the circle radius, not bounding box, otherwise we might miss some closer in the next step
                    $close_posts[$geo_post->post_id] = $post_distance;
                }
            }

            $search_distance *= 2;
        }

        asort($close_posts);

        return $close_posts;
    }

}

$monkeyman_Geo_ClosestX_instace = new Monkeyman_Geo_ClosestX();

8

सबसे पहले आपको एक टेबल चाहिए जो कुछ इस तरह दिखे:

zip_code    lat     lon
10001       40.77    73.98

... प्रत्येक ज़िप कोड के लिए आबादी। यदि आप इस तरह से देखना चाहते हैं तो आप शहर और राज्य क्षेत्रों को जोड़कर इस पर विस्तार कर सकते हैं।

फिर प्रत्येक स्टोर को एक ज़िप कोड दिया जा सकता है, और जब आपको दूरी की गणना करने की आवश्यकता होती है तो आप स्टोर डेटा के लिए lat / long table में शामिल हो सकते हैं।

फिर आप स्टोर और उपयोगकर्ता के ज़िप कोड के लिए अक्षांश और देशांतर प्राप्त करने के लिए उस तालिका को क्वेरी करेंगे। एक बार जब आप इसे प्राप्त कर लेते हैं, तो आप अपने सरणी को आबाद कर सकते हैं और इसे "दूरी प्राप्त करें" फ़ंक्शन में पास कर सकते हैं:

$user_location = array(
    'latitude' => 42.75,
    'longitude' => 73.80,
);

$output = array();
$results = $wpdb->get_results("SELECT id, zip_code, lat, lon FROM store_table");
foreach ( $results as $store ) {
    $store_location = array(
        'zip_code' => $store->zip_code, // 10001
        'latitude' => $store->lat, // 40.77
        'longitude' => $store->lon, // 73.98
    );

    $distance = get_distance($store_location, $user_location, 'miles');

    $output[$distance][$store->id] = $store_location;
}

ksort($output);

foreach ($output as $distance => $store) {
    foreach ( $store as $id => $location ) {
        echo 'Store ' . $id . ' is ' . $distance . ' away';
    }
}

function get_distance($store_location, $user_location, $units = 'miles') {
    if ( $store_location['longitude'] == $user_location['longitude'] &&
    $store_location['latitude'] == $user_location['latitude']){
        return 0;

    $theta = ($store_location['longitude'] - $user_location['longitude']);
    $distance = sin(deg2rad($store_location['latitude'])) * sin(deg2rad($user_location['latitude'])) + cos(deg2rad($store_location['latitude'])) * cos(deg2rad($user_location['latitude'])) * cos(deg2rad($theta));
    $distance = acos($distance);
    $distance = rad2deg($distance);
    $distance = $distance * 60 * 1.1515;

    if ( 'kilometers' == $units ) {
        $distance = $distance * 1.609344;
    }

    return round($distance);
}

यह एक सबूत की अवधारणा के रूप में है, न कि कोड जिसे मैं वास्तव में लागू करने की सलाह दूंगा। यदि आपके पास 10,000 स्टोर हैं, उदाहरण के लिए, यह उन सभी को क्वेरी करने और हर अनुरोध पर उन्हें सॉर्ट करने के लिए एक बहुत महंगा ऑपरेशन होगा।


क्या परिणाम कैश्ड हो सकते हैं? इसके अलावा, ज़िप कोड डेटाबेसों में से किसी एक को उपलब्ध कॉम्युलरली (या मुफ्त में) क्वेरी करना आसान होगा?
मैट

1
@matt - व्यावसायिक रूप से उपलब्ध या निःशुल्क उपलब्ध क्वेरी से आपका क्या अभिप्राय है? कैशिंग हमेशा संभव होना चाहिए, codex.wordpress.org/Transients_API
hakre

@ ठाकरे: कोई बात नहीं, मुझे लगता है कि मैं अब अपने सिर पर बात कर रहा हूं। मैं दूरी प्राप्त करने के लिए एक ज़िप कोड डेटाबेस (USPS, Google मैप्स ...) का उपयोग करने के बारे में बात कर रहा हूं, लेकिन मुझे यह महसूस नहीं हुआ कि वे शायद दूरी को स्टोर नहीं करते हैं, वे बस ज़िप कोड और निर्देशांक संग्रहीत करते हैं और यह होगा इसकी गणना करने के लिए मेरे पास रहो।
मैट

3

MySQL प्रलेखन में स्थानिक एक्सटेंशन की जानकारी भी शामिल है। अजीब तरह से, मानक दूरी () फ़ंक्शन उपलब्ध नहीं है, लेकिन इस पृष्ठ की जांच करें: http://dev.mysql.com/tech-resources/articles/4.1/gis-with-mysql.html विवरणों को "कैसे परिवर्तित करें" के लिए। एक लाइनिंग के लिए दो बिंदु मान और फिर उस की लंबाई की गणना करें। "

ध्यान दें कि प्रत्येक विक्रेता को एक ज़िप कोड के "सेंट्रोइड" का प्रतिनिधित्व करने वाले विभिन्न अक्षांश और देशांतरों की पेशकश करने की संभावना है। यह भी जानने योग्य है कि कोई वास्तविक परिभाषित ज़िप कोड "सीमा" फाइलें नहीं हैं। प्रत्येक विक्रेता के पास सीमाओं का अपना सेट होगा जो उन पते की विशिष्ट सूची से मेल खाता है जो यूएसपीएस ज़िप कोड बनाते हैं। (उदाहरण के लिए, कुछ "सीमाओं" में आपको सड़क के दोनों किनारों को, दूसरों में, बस एक को शामिल करने की आवश्यकता होगी।) ज़िप कोड सारणीकरण क्षेत्र (ZCTAs), व्यापक रूप से विक्रेताओं द्वारा उपयोग किया जाता है, "ज़िप कोड वितरण क्षेत्रों को ठीक से चित्रित न करें," और मेल डिलीवरी के लिए उपयोग किए जाने वाले सभी ज़िप कोड शामिल न करें " http://www.census.gov/geo/www/cob/zt_metadN.html

कई डाउनटाउन व्यवसायों का अपना ज़िप कोड होगा। आप संभव के रूप में एक डेटासेट पूरा करना चाहते हैं, इसलिए सुनिश्चित करें कि आप ज़िपकोड की एक सूची पाते हैं जिसमें "बिंदु" ज़िप कोड (आमतौर पर व्यवसाय) और "सीमा" ज़िप कोड दोनों शामिल हैं।

मुझे http://www.semaphorecorp.com/ से जिपकोड डेटा के साथ काम करने का अनुभव है । यहां तक ​​कि 100% सटीक नहीं था। उदाहरण के लिए, जब मेरे परिसर ने एक नया मेलिंग पता और नया ज़िप कोड लिया, तो ज़िप गलत हो गया था। उस ने कहा, यह एकमात्र डेटा स्रोत था जो मैंने पाया कि यहां तक ​​कि नए ज़िप कोड को भी HAD किया, इसलिए इसके बनने के तुरंत बाद।

मुझे अपनी पुस्तक में एक नुस्खा मिला था कि कैसे आपके अनुरोध को पूरा किया जाए ... द्रुपाल में। यह Google मैप्स टूल मॉड्यूल ( http://drupal.org/project/gmaps , http://drupal.org/project/gmap , भी एक योग्य मॉड्यूल के साथ भ्रमित न होने के लिए) पर निर्भर करता है । आपको कुछ सहायक नमूना मिल सकता है। उन मॉड्यूल में कोड, हालांकि, वे वर्डप्रेस में बॉक्स से बाहर काम नहीं करेंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.