2

Sphinxにはすでに2つのデータソースがあります。

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
    ...
}

PHP Sphinx APIを使用して、名前で一致する都市を検索し、緯度/経度から25マイル以内のリストを問題なく検索しましたが、今度はそれらに「参加」する必要があります...できること:

a)名前で都市を検索する場合は、25マイル以内にリストがある都市のみを返します。b)1つの都市(緯度/経度がわかっています)の結果を表示している場合は、25マイル以内にリストがある最も近い3つの都市をプルします。そのうちの

これらの2つのルックアップを実行するために単一のスフィンクス検索を構築する方法はありますか?

以下のコメントチェーンに基づいて編集します。

都市テーブルを更新して、Pointタイプのフィールドポイントを含め、その上に空間インデックスを作成しました。

>citys_copyについて説明します。
+ ------------- + ----------------------- + ------ + ---- -+ --------- + ---------------- +
| フィールド| タイプ| ヌル| キー| デフォルト| エクストラ|
+ ------------- + ----------------------- + ------ + ---- -+ --------- + ---------------- +
| id | Mediumint(7)unsigned | いいえ| PRI | NULL | auto_increment |
| city_name | varchar(64)| いいえ| MUL | NULL | |
| state_name | varchar(64)| いいえ| | NULL | |
| state_abbr | varchar(8)| いいえ| | NULL | |
| county_name | varchar(64)| いいえ| | NULL | |
| county_id | smallint(3)unsigned | いいえ| | NULL | |
| 緯度| float(13,10)| いいえ| MUL | NULL | |
| 経度| float(13,10)| いいえ| | NULL | |
| 人口| int(8)unsigned | いいえ| MUL | NULL | |
| ポイント| ポイント| いいえ| MUL | NULL | |
+ ------------- + ----------------------- + ------ + ---- -+ --------- + ---------------- +

>cities_copyからのインデックスを表示します。
+ ------------- + ------------ + ------------ + --------- ----- + ------------- + ----------- + ------------- + ---- ------ + -------- + ------ + ------------ + --------- +
| テーブル| Non_unique | Key_name | Seq_in_index | Column_name | 照合| カーディナリティ| Sub_part | パック| ヌル| Index_type | コメント|
+ ------------- + ------------ + ------------ + --------- ----- + ------------- + ----------- + ------------- + ---- ------ + -------- + ------ + ------------ + --------- +
| citys_copy | 0 | プライマリー| 1 | id | A | 23990 | NULL | NULL | | BTREE | |
| citys_copy | 0 | 市/州| 1 | city_name | A | NULL | NULL | NULL | | BTREE | |
| citys_copy | 0 | 市/州| 2 | state_abbr | A | 23990 | NULL | NULL | | BTREE | |
| citys_copy | 1 | 緯度/経度| 1 | 緯度| A | NULL | NULL | NULL | | BTREE | |
| citys_copy | 1 | 緯度/経度| 2 | 経度| A | NULL | NULL | NULL | | BTREE | |
| citys_copy | 1 | 人口| 1 | 人口| A | NULL | NULL | NULL | | BTREE | |
| citys_copy | 1 | ポイント| 1 | ポイント| A | NULL | 32 | NULL | | 空間| |
+ ------------- + ------------ + ------------ + --------- ----- + ------------- + ----------- + ------------- + ---- ------ + -------- + ------ + ------------ + --------- +

しかし、緯度/経度データからポイントを作成するためにデータを更新しようとすると、エラーが発生します。

>都市を更新する_copysetpoint= Point(latitude、longitude);
GEOMETRYフィールドに送信したデータからジオメトリオブジェクトを取得できません

私の構文はここから外れていますか、それとも他の問題が発生していますか?

4

1 に答える 1

2

次のことを行う必要があります。

  • を保持する追加のGEOMETRYフィールドを作成し、Point(Latitude, Longitude)緯度と経度を地球平面のメートル座標に置き換えます。

  • SPATIALこのフィールドにインデックスを作成します

  • 最初のクエリを修正します。

    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
            )
    

最も近い3つの都市を見つけるには、次のクエリを発行します。

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

ただし、都市がたくさんある場合はあまり効率的ではないことに注意してください。

効率を上げるには、テッセレーションテーブル(場所の近くの地球の表面を並べて表示します)を作成し、並べて表示する順序を計算して結合する必要があります。

示す簡単なスクリプトは次のとおりです。

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
于 2009-10-13T13:19:10.253 に答える