php-飛行場の自動提案-複数の列にわたって「ベストマッチファースト」を注文する方法は?
次のテーブル構造を前提としています:
id iata icao name
1 ANC PANC Anchorage - Ted Stevens International
2 LHR EGLL London - Heathrow
3 LGW EGKK London - Gatwick
4 MDZ SAME Mendoza - Governor Francisco Gabrielli International
旅行代理店サイトの自動提案フィールドで期待されるように、「ベストマッチファースト」の順序でレコードを抽出するための最良の方法は何ですか? 1つの列の="string"
の一致は、他の列の LIKE "%string%"
の一致よりも優先される必要があります。その後、「名前」のアルファベット順がおそらく私が欲しいものです。
たとえば、「anc」を検索すると、1行目から4行目が返されます。「lon」は3行目から2行目です。
IATAコードは常に3文字、ICAOは常に4文字です。ただし、いずれかまたは両方がNULLの場合があります。
AJAXが3文字を送信し、そこからJavascriptでフィルタリングすることを期待しますが、入力が3文字になるとは想定できません。Javascript以外のユーザーは任意の長さの文字列を送信します。
これはPHPでMySQLを使用して行っています。
答え :
解決策:
これは割るのが難しいナットです。これが私が過去に使用したいくつかの要因であり、その後にそれらの相対的な重みが続きます。
- 完全一致:50(基本的に:100%成功)
- レーベンシュタイン距離<2:25(スペルミスを取り除く-かなり集中的なアルゴですが)
- 名前の先頭での部分一致:15
- 名前のどこかで部分一致:10
完全一致はこれに基づいて100ポイントを獲得します(すべて一致します)。次に、単純に重量の合計で並べ替えます。
私のデータセット(曲名)の場合、これはかなり良い結果をもたらしました。それがあなたのものにどのように耐えるかわからない。
あなたの場合、「入力が3文字の場合、IATAに一致する場合は50ポイント、4文字の場合、ICAOに一致する場合は50ポイント」をリストに追加します。
SQLでこれを行う方法:
SELECT SUM( IF(`name` = :Input, 50, 0), IF(`iata` = :Input, 50, 0), IF(`icao` = :Input, 50, 0), IF(`name` LIKE CONCAT('%', :Input, '%'), 25, 0), ... ) FROM Table;
並べ替えはPHPで行われました。
美しくもエレガントでもありませんが、うまくいきました。
答え :
解決策:
これはかなり単純なアプローチです:
SELECT ID, 1 As Certainty FROM airfields where iata = @searchValue OR icao = @searchValue OR name = @searchValue
UNION
SELECT ID, 2 FROM airfields where iata <> @searchValue AND icao <> @searchValue AND NAME <> @searchValue
AND (iata LIKE '%' + @searchValue + '%" OR icao LIKE '%' + @searchValue + '%" OR name LIKE '%' + @searchValue + '%")
ORDER BY Certainty
したがって、完全一致が常に優先されます。その後、注文を厳しくしたいと思うでしょう。
答え :
解決策:
MyISAMタイプのテーブルを実行している場合は、フルテキストインデックスを使用してください。マッチアゲインストは、結果を並べ替えることができる関連性を提供します。 http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html#function_match
代わりにApacheSolrまたはSphinxを使用してください。
同様の質問
私たちのウェブサイトで同様の質問で答えを見つけてください。