記事の投稿ができ、各記事に対してタグ付けができるサイトを検討しています。
その中でワード検索を行いたいと考えています。
例を示します。
[postsテーブル]
pid title city txt
1 映画 東京 のびたがついに大活躍
2 映画 東京 スポーツ系物語
3 演劇 大阪 お笑い系
・・・
[tagsテーブル]
tid pid tag
1 1 どらえもん
2 1 面白い
3 2 青春
・・・
【検索の仕様】
・検索対象フィールドは以下
postsテーブルのtitle, city, txt および tagsテーブルのtag
・複数語検索に対応(空白区切りのAND検索)
例えば、
検索窓に「のびた どらえもん」と入れるとpid1がマッチします。
(検索語がpostsのtxtとtagsのtagにlikeマッチ)
「どらえ 面白」と入れるとpid1がマッチします。
(検索語がtagsのtagにlikeマッチ)
同様に「映画 東京 スポーツ」だとpid2がlikeマッチします。
環境はMySQL、PHPになります。
ここ数日、どのようなSQL文を組んだら良いのか悩んでいます。
アドバイス頂ければ嬉しいです。
(できれば、補足情報としてtagにマッチしたどうかが分かるフラグ情報まで得られればベストです。)
今回の場合は、
[postsテーブル]と[tagsテーブル]をJOINして
これをSQLで検索する方向で考えてみるべき
たぶん、SQL1回でOKだと思うけど。
トリッキーでなくて普通に使われる手法。
JOIN自体がトリッキーなら、方法はプログラムでがんばるしかない。
>今回の仕組みですと「映画 東京 スポーツ」の場合は最低6回のSQLが発行されます。
>(ループ3回、ループ内で2回(postsテーブルおよびtagsテーブルを対象))
>出来ればSQL発行回数を抑えたいのですが、妙案はありませんでしょうか。
>しかしトリッキーにSQLを使用するのは避けたいと思いますので、通常適用される範囲で良い案があれば教えて頂けると嬉しいです。
[postsテーブル]と[tagsテーブル]をJOINして
SQLで検索すれば、SQL発行回数は減りますが・・・。
JOINは普通の方法ですし、そんなに遅いわけでもなくて
プログラムでループしてマッチさせるより早いこともあります。
これ、データ件数とかにもよるんですね。
データ件数が多くなるほど、SQLで力尽くJOINというのは遅くなる傾向にあり
プログラムで力尽くの方がかえって早くなるということがあります。
SQLの発行回数よりも
実際の処理時間
SQL3回と
SQL6回でも
6回の方が早いことも多々ありますよ。
検索に使用する単語は 一つに したほうがいいですね。
たとえば 「映画 東京 スポーツ」の場合は 「映画」、「東京」、「スポーツ」の3つにわけて 3回ループして 取得する。
上記のキーワードで
[postsテーブル]
titleとcityとtxtに 対して それぞれ likeでORで pidを取得する。
[tagsテーブル]
こちらは tagで like 検索して pidを取得する。
これを 単語数繰り返して どの 単語でも 取得できた pidを 検索結果とする。
こんな感じで できますか?
>この場合、ループ内ではpidのみを取得する形が良いでしょうか?
そうですね。メモリとの兼ね合いですが、件数が少ないようでしたら 全部取得したほうが ラクでしょう。
ま、これぐらいの項目数ならば 全部 取得してもいいと思います。
抽出内容が 同じものは UNION で SQLを連結させれば 発行回数自体は 減らせます。
ありがとうございます。
PHP側での力技部分が多くなりますが、確かにこの仕組みを採用すれば今回の検索は実現できそうですね。
候補の一つとして考えます。
今回の場合は、
[postsテーブル]と[tagsテーブル]をJOINして
これをSQLで検索する方向で考えてみるべき
たぶん、SQL1回でOKだと思うけど。
トリッキーでなくて普通に使われる手法。
JOIN自体がトリッキーなら、方法はプログラムでがんばるしかない。
>今回の仕組みですと「映画 東京 スポーツ」の場合は最低6回のSQLが発行されます。
>(ループ3回、ループ内で2回(postsテーブルおよびtagsテーブルを対象))
>出来ればSQL発行回数を抑えたいのですが、妙案はありませんでしょうか。
>しかしトリッキーにSQLを使用するのは避けたいと思いますので、通常適用される範囲で良い案があれば教えて頂けると嬉しいです。
[postsテーブル]と[tagsテーブル]をJOINして
SQLで検索すれば、SQL発行回数は減りますが・・・。
JOINは普通の方法ですし、そんなに遅いわけでもなくて
プログラムでループしてマッチさせるより早いこともあります。
これ、データ件数とかにもよるんですね。
データ件数が多くなるほど、SQLで力尽くJOINというのは遅くなる傾向にあり
プログラムで力尽くの方がかえって早くなるということがあります。
SQLの発行回数よりも
実際の処理時間
SQL3回と
SQL6回でも
6回の方が早いことも多々ありますよ。
■方法1
一番簡単なのは、
1記事につけれるタグの数に制限をつけて
[tagsテーブル]を
pid tag名1 tag名2
のような構造にして、
LEFT JIONでなくて1対1のJOINをすれば簡単になると思うが・・
テーブル構造も2テーブルでなくて
1.記事
2.pid id 対応表
3.タグマスタ id tag名
の用に分けてみても。
現状、タグidって存在する意味さえなさそうだけど。
ワード検索で
・記事タイトル関係とタグとを同時に扱う
・AND条件
この2つが難しくしてると思う。
SQLのIN句
IN フィールド名 (SECECL * FROM TABLE WHERE ***)
または
IN フィールド名 (値1,値2,値3 ***)
みたいな物も使えると思う。
あとlike検索は元々遅いので
この方式自体がどうかなというところもあると思う。
ありがとうございます。
>1記事につけれるタグの数に制限をつけて
>[tagsテーブル]を
>pid tag名1 tag名2
>のような構造にして、
うーん、こちらの方法は余りスマートではありませんね。
>テーブル構造も2テーブルでなくて
>1.記事
>2.pid id 対応表
>3.タグマスタ id tag名
>の用に分けてみても。
ありがとうございます。
この3テーブル構成にした場合は、現在ネックになっている部分は解決するのでしょうか?(結論として1対1のjoinになる?)
頭がまわらず、この構成にする利点が良く掴めておりません。
>ワード検索で
>・記事タイトル関係とタグとを同時に扱う
>・AND条件
>この2つが難しくしてると思う。
おっしゃる通りで悩んでいます。
>あとlike検索は元々遅いので
>この方式自体がどうかなというところもあると思う。
他にどんな方式があるのでしょうか?
ヒントや障りだけでも教えて頂けると助かります。
■方法1
2012/04/20 21:11:17一番簡単なのは、
1記事につけれるタグの数に制限をつけて
[tagsテーブル]を
pid tag名1 tag名2
のような構造にして、
LEFT JIONでなくて1対1のJOINをすれば簡単になると思うが・・
テーブル構造も2テーブルでなくて
1.記事
2.pid id 対応表
3.タグマスタ id tag名
の用に分けてみても。
現状、タグidって存在する意味さえなさそうだけど。
ワード検索で
・記事タイトル関係とタグとを同時に扱う
・AND条件
この2つが難しくしてると思う。
SQLのIN句
IN フィールド名 (SECECL * FROM TABLE WHERE ***)
または
IN フィールド名 (値1,値2,値3 ***)
みたいな物も使えると思う。
あとlike検索は元々遅いので
この方式自体がどうかなというところもあると思う。
ありがとうございます。
2012/04/21 11:46:02>1記事につけれるタグの数に制限をつけて
>[tagsテーブル]を
>pid tag名1 tag名2
>のような構造にして、
うーん、こちらの方法は余りスマートではありませんね。
>テーブル構造も2テーブルでなくて
>1.記事
>2.pid id 対応表
>3.タグマスタ id tag名
>の用に分けてみても。
ありがとうございます。
この3テーブル構成にした場合は、現在ネックになっている部分は解決するのでしょうか?(結論として1対1のjoinになる?)
頭がまわらず、この構成にする利点が良く掴めておりません。
>ワード検索で
>・記事タイトル関係とタグとを同時に扱う
>・AND条件
>この2つが難しくしてると思う。
おっしゃる通りで悩んでいます。
>あとlike検索は元々遅いので
>この方式自体がどうかなというところもあると思う。
他にどんな方式があるのでしょうか?
ヒントや障りだけでも教えて頂けると助かります。