7

音楽ライブラリ アプリケーションで使用される MySQL データベースに 3 つのテーブルがあります。

Genreテーブルには次の列があります。

  • id
  • title(ストリング)

Albumテーブルには次の列があります。

  • id
  • genre_id( への外部キーGenre.id)
  • title(ストリング)
  • artist(ストリング)

Trackテーブルには次の列があります。

  • id
  • album_id( への外部キーAlbum.id)
  • title(ストリング)

それぞれAlbumに任意の数の を含めることができTracks、それぞれTrackに を 1 つAlbum、それぞれに をAlbum1つ持つことができますGenre


ユーザーが任意の数のキーワードを入力してすべてを検索できるようにするキーワード検索を実装したいと考えていますTracks

  • 一致するtitle
  • Album一致するtitleまたはartist
  • または に一致する を使用していAlbumます。Genretitle

結果は関連性でソートする必要があります。各フィールドに関連性のランキングがあれば素晴らしいことです。たとえば、 のtitleは のTrackよりも重要な場合がtitleありGenreます。

また、ソリューションでは何らかの形式の部分検索を使用する必要があります。の検索は、最初にofrubberですべて一致Tracksし、次に一致( =wildcard) で一致し、次に に移動する必要があります。ただし、私はこれらの詳細についてはそれほど固執していません。特定のニーズに合わせて微調整できる、より一般的なソリューションを探しています。titleRubberTrackstitle*rubber**Albums

また、LAMP スタック、Linux、Apache、MySQL、および PHP を使用していることにも言及する必要があります。


このキーワード検索を実装する最良の方法は何ですか?


更新:全文検索を使用してこれを実装しようとしており、次の SQL ステートメントを考え出しました。

CREATE TABLE `Genre` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` text NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

INSERT INTO `Genre` VALUES(1, 'Rock');

CREATE TABLE `Album` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `genre_id` int(11) NOT NULL,
  `title` text NOT NULL,
  `artist` text,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`, `artist`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

INSERT INTO `Album` VALUES(1, 1, 'Rubber Soul', 'The Beatles');

CREATE TABLE `Track` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `album_id` int(11) NOT NULL,
  `title` text NOT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

INSERT INTO `Track` VALUES(1, 1, 'Drive My Car');
INSERT INTO `Track` VALUES(2, 1, 'What Goes On');
INSERT INTO `Track` VALUES(3, 1, 'Run For Your Life');
INSERT INTO `Track` VALUES(4, 1, 'Girl');
4

3 に答える 3

5

ApacheSolrを使用します。データインポートハンドラーを使用して、すべてのテーブルを結合するSQLクエリを定義し、結合されたデータの結果からフルテキストインデックスを作成します。


MATCH()に対してargsとして指定された列は、インデックスで定義したのと同じ順序で、インデックスに定義した列である必要があります。ただし、MySQLの複数のテーブルにインデックス(フルテキストまたはその他)を定義することはできません。

したがって、これを行うことはできません。

WHERE MATCH (g.title, a.title, a.artist, t.title) AGAINST ('beatles')

ブールモードと自然言語モードのどちらを使用しているかは関係ありません。

これを行う必要があります:

WHERE MATCH (g.title) AGAINST ('beatles')
   OR MATCH (a.title, a.artist) AGAINST ('beatles')
   OR MATCH (t.title) AGAINST ('beatles')

また、MySQLでの実用的な全文検索のプレゼンテーションにも興味があるかもしれません。

于 2010-07-16T22:24:31.053 に答える
1

検索する 4 つの列にフルテキスト インデックスを定義してから、次の操作を行います。

SELECT * FROM genre AS g
  LEFT JOIN album AS a ON g.id = a.genre_id
  LEFT JOIN tracks AS t ON a.id = t.album_id
  WHERE MATCH (g.title,  a.title, a.artist, t.title) AGAINST ('searchstring');

結果は関連性によってソートされます。全文検索の詳細については、 http ://dev.mysql.com/doc/refman/5.0/en/fulltext-natural-language.html を参照してください。

于 2010-07-16T22:35:25.900 に答える
0

私は Sphinx のようなものを使用します。クエリからインデックスを作成し、それをクエリできます。理解するのは少し難しいですが、結果は mysql AGAINST よりも 10 倍優れており、後で速度の問題が発生することはありません。

于 2010-07-19T17:24:18.090 に答える