listeleri yakın şehirleri bulabilirsiniz (işletmeler)

1 Cevap php

Zaten Sfenks iki veri kaynakları vardır:

source cities {
    ...
    sql_query = SELECT id, city_name, state_name, state_abbr, latitude,
                longitude, population FROM cities;
    sql_attr_uint  = population
    sql_attr_float = latitude
    sql_attr_float = longitude
    ...
}

source listings {
    ...
    sql_query = SELECT entry_id, title, url_title, category_names, 
                address1, address2, city, state, zip, latitude, longitude,
                listing_summary, listing_url, extended_info FROM listings;
    sql_attr_float = latitude
    sql_attr_float = longitude
    ...
}

Ben herhangi bir sorun olmadan bir enlem / boylam 25 kilometre mesafedeki listeleri için adı ve aramalar ile eşleşen şehirler için arama yaptım PHP Sfenks API kullanarak, ama şimdi ben onları 'katılmak' sıralamak gerekiyor ... Ben olmak istiyorum edebilmek için:

a) when searching for cities by name, return only cities having listings within 25 miles of them and b) when I'm viewing results for one city (lat/long is known), pull the 3 nearest cities that have listings within 25 miles of them

Bu iki aramalarını gerçekleştirmek için tek bir sfenks arama oluşturmak için bir yolu var mı?

Edit based on comment chain below:

Ben tip Point bir alan nokta eklemeyi benim şehirler tablo güncellenir ve bunun üzerine bir kayma dizin oluşturduk:

> describe cities_copy;
+-------------+-----------------------+------+-----+---------+----------------+
| Field       | Type                  | Null | Key | Default | Extra          |
+-------------+-----------------------+------+-----+---------+----------------+
| id          | mediumint(7) unsigned | NO   | PRI | NULL    | auto_increment |
| city_name   | varchar(64)           | NO   | MUL | NULL    |                |
| state_name  | varchar(64)           | NO   |     | NULL    |                |
| state_abbr  | varchar(8)            | NO   |     | NULL    |                |
| county_name | varchar(64)           | NO   |     | NULL    |                |
| county_id   | smallint(3) unsigned  | NO   |     | NULL    |                |
| latitude    | float(13,10)          | NO   | MUL | NULL    |                |
| longitude   | float(13,10)          | NO   |     | NULL    |                |
| population  | int(8) unsigned       | NO   | MUL | NULL    |                |
| point       | point                 | NO   | MUL | NULL    |                |
+-------------+-----------------------+------+-----+---------+----------------+

> show indexes from cities_copy;
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table       | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| cities_copy | 0          | PRIMARY    | 1            | id          | A         | 23990       | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 0          | city/state | 1            | city_name   | A         | NULL        | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 0          | city/state | 2            | state_abbr  | A         | 23990       | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 1          | lat/long   | 1            | latitude    | A         | NULL        | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 1          | lat/long   | 2            | longitude   | A         | NULL        | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 1          | population | 1            | population  | A         | NULL        | NULL     | NULL   |      | BTREE      |         |
| cities_copy | 1          | point      | 1            | point       | A         | NULL        | 32       | NULL   |      | SPATIAL    |         |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

Uzun / lat verileri üzerinden noktaları oluşturmak için verileri güncelleştirmeye çalıştığınızda ama bir hata alıyorum:

> update cities_copy set point = Point(latitude, longitude);
Cannot get geometry object from data you send to the GEOMETRY field

Burada benim sözdizimi kapalı ya da başka bir sorun haline çalıştırıyorum?

1 Cevap

Sen aşağıdakileri yapmanız gerekir:

  • Düz toprak için metrik koordinatlar ile enlem ve boylamı yerine, Point(Latitude, Longitude) yapacağını ek bir GEOMETRY alanı oluşturun.

  • Bu alanda bir SPATIAL dizin oluşturma

  • Ilk sorguyu Fix:

    SELECT  *
    FROM    cities cc
    WHERE   EXISTS
            (
            SELECT  NULL
            FROM    listings cp
            WHERE   MBRContains(LineString(Point(cc.latitude - 25, cc.longitude - 25), Point(cc.latitude + 25, cc.longitude + 25)), cp.Coords)
                    AND GLength(LineString(cc.Coords, cp.Coords)) <= 25
            )
    

Üç yakın şehirleri öğrenmek için, bu sorguyu çalıştırın:

SELECT  cp.*
FROM    cities cc
CROSS JOIN
        cities cp
WHERE   cc.id = @id
ORDER BY
        GLength(LinePoint(cc.Coords, cp.Coords))
LIMIT 3

, Ancak şehirlerin çok varsa çok verimli olmayacağını unutmayın.

Verimli hale getirmek için, (Eğer yerlerde yakın çini Dünya yüzeyini hangi), fayans yakınlık sırasını hesaplamak ve onlarla katılmak bir tesselation tablo oluşturmanız gerekir.

Burada göstermek için basit bir script var:

CREATE TABLE t_spatial (id INT NOT NULL PRIMARY KEY, coords Point) ENGINE=MyISAM;

INSERT
INTO    t_spatial
VALUES
(1, Point(0, 0)),
(2, Point(0, 1)),
(3, Point(1, 0)),
(4, Point(1, 1));

SELECT  s1.id, s2.id, GLength(LineString(s1.coords, s2.coords))
FROM    t_spatial s1
CROSS JOIN
        t_spatial s2