須藤様<div><br></div><div>佐藤です。</div><div><br></div><div>ご連絡ありがとうございます。</div><div>sub_filterはまさにやりたかったことです。</div><div><br></div><div>教えていただいた内容は理解できました。</div>groongaを使い込んで、確認をしたいとおもいます。<br><div><br>2015年5月9日土曜日、Kouhei Sutou<<a href="mailto:kou****@clear*****">kou****@clear*****</a>>さんは書きました:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">須藤です。<br>
<br>
少し高度な使い方になるのですが、selectの回数を減らす方法があ<br>
るので補足します。<br>
<br>
In <<a href="javascript:;" onclick="_e(event, 'cvml', '20150****@clear*****')">20150****@clear*****</a>><br>
"[groonga-dev,03210] Re: selectとin_valuesの制限事項について" on Fri, 08 May 2015 21:59:06 +0900 (JST),<br>
Kouhei Sutou <<a href="javascript:;" onclick="_e(event, 'cvml', 'kou****@clear*****')">kou****@clear*****</a>> wrote:<br>
<br>
> select \<br>
> --table Keywords \<br>
> --filter '_key *T "Groonga and Mroonga are good!"' \<br>
> --output_columns _key<br>
> # -> ["groonga", "mroonga"]<br>
><br>
> select \<br>
> --table Users \<br>
> --match_columns keywords \<br>
> --query 'groonga OR mroonga'<br>
> # -> [["user1", ["groonga", "mysql"]],<br>
> # ["user3", ["mroonga"]]]<br>
<br>
ここで1つ目のselectの結果を2つ目のselectの条件に使っているん<br>
ですが、次のようにsub_filter()(*)を使うと一回のselectで実現<br>
できます。<br>
<br>
(*) <a href="http://groonga.org/ja/docs/reference/functions/sub_filter.html" target="_blank">http://groonga.org/ja/docs/reference/functions/sub_filter.html</a><br>
<br>
---<br>
select \<br>
--table Users \<br>
--filter 'sub_filter(keywords, "_key *T \\"Groonga and Mroonga are good!\\"")'<br>
# -> [["user1", ["groonga", "mysql"]],<br>
# ["user3", ["mroonga"]]]<br>
---<br>
<br>
sub_filter()はSQLでいう<br>
<br>
WHERE xxx_id IN (SELECT id FROM xxx WHERE ...)<br>
<br>
のようなことができる機能です。<br>
<br>
sub_filter()を使えるのは↑のSQLのように<br>
<br>
1. 条件が参照型のカラム<br>
(別のテーブルのプライマリーキーを参照しているカラム)<br>
に対するIN<br>
2. サブSELECTの結果は参照されているテーブルのプライマリー<br>
キー(レコード)の集合<br>
<br>
の場合だけです。<br>
<br>
今回のケースではUsers.keywordsがKeywordsテーブルの参照型で、<br>
それで絞り込みたいので1.を満たしています。また、<br>
「_key *T "..."」の結果で絞り込んだ結果はKeywordsテーブルの<br>
レコードなので2.も満たしています。<br>
<br>
補足:<br>
↑の説明は少し簡略化していて、実はsub_filterを使うにはもうひ<br>
とつ条件があります。参照されているテーブルから元のselectのテー<br>
ブルへのインデックスがあること、という条件です。今回の場合だと<br>
<br>
column_create Keywords users_keywords COLUMN_INDEX Users keywords<br>
<br>
がそれにあたります。<br>
<br>
絵を書けばピンときやすいんですが、テキストでの説明だとこんな<br>
感じなので省略しました。。。<br>
<br>
<br>
<br>
sub_filter()は、他にも第二引数は「文字列」でfilterと同じ書式<br>
の条件を書かないといけないので「\」や「"」のエスケープが必要<br>
になるなど、使い方が難しい機能ではあるのですが、高度なことが<br>
できるので参考までに紹介しました。<br>
<br>
<br>
動かせるスキーマとデータとselectは次の通りです。<br>
<br>
---<br>
table_create Articles TABLE_HASH_KEY ShortText<br>
column_create Articles content COLUMN_SCALAR Text<br>
<br>
table_create Keywords TABLE_PAT_KEY ShortText \<br>
--normalizer NormalizerAuto<br>
# 表示するときは正規化しない状態で表示したいならあると便利<br>
# 例: 「groonga」ではなく「Groonga」と表示したい<br>
# column_create Keywords label COLUMN_SCALAR ShortText<br>
<br>
table_create Users TABLE_HASH_KEY ShortText<br>
column_create Users keywords COLUMN_VECTOR Keywords<br>
<br>
<br>
column_create Keywords users_keywords COLUMN_INDEX Users keywords<br>
<br>
<br>
load --table Articles<br>
[<br>
{"_key": "article1", "content": "Groonga and Mroonga are good!"},<br>
{"_key": "article2", "content": "MySQL and PostgreSQL are good!"},<br>
{"_key": "article3", "content": "Groonga + MySQL = Mroonga!"}<br>
]<br>
<br>
load --table Users<br>
[<br>
{"_key": "user1", "keywords": ["Groonga", "MySQL"]},<br>
{"_key": "user2", "keywords": ["MySQL"]},<br>
{"_key": "user3", "keywords": ["Mroonga"]}<br>
{"_key": "user4", "keywords": ["PostgreSQL"]}<br>
]<br>
<br>
<br>
select \<br>
--table Articles \<br>
--filter '_key == "article1"' \<br>
--output_columns content<br>
# -> "Groonga and Mroonga are good!"<br>
<br>
select \<br>
--table Keywords \<br>
--filter '_key *T "Groonga and Mroonga are good!"' \<br>
--output_columns _key<br>
# -> ["groonga", "mroonga"]<br>
<br>
select \<br>
--table Users \<br>
--filter 'sub_filter(keywords, "_key *T \\"Groonga and Mroonga are good!\\"")'<br>
# -> [["user1", ["groonga", "mysql"]],<br>
# ["user3", ["mroonga"]]]<br>
---<br>
<br>
<br>
--<br>
須藤 功平 <<a href="javascript:;" onclick="_e(event, 'cvml', 'kou****@clear*****')">kou****@clear*****</a>><br>
株式会社クリアコード <<a href="http://www.clear-code.com/" target="_blank">http://www.clear-code.com/</a>><br>
<br>
Groongaベースの全文検索システムを総合サポート:<br>
<a href="http://groonga.org/ja/support/" target="_blank">http://groonga.org/ja/support/</a><br>
パッチ採用 - プログラミングが楽しい人向けの採用プロセス:<br>
<a href="http://www.clear-code.com/recruitment/" target="_blank">http://www.clear-code.com/recruitment/</a><br>
プログラミングが好きな学生のための勉強会:<br>
<a href="http://www.seplus.jp/sezemi/" target="_blank">http://www.seplus.jp/sezemi/</a><br>
<br>
_______________________________________________<br>
groonga-dev mailing list<br>
<a href="javascript:;" onclick="_e(event, 'cvml', 'groon****@lists*****')">groon****@lists*****</a><br>
<a href="http://lists.sourceforge.jp/mailman/listinfo/groonga-dev" target="_blank">http://lists.sourceforge.jp/mailman/listinfo/groonga-dev</a><br>
</blockquote></div><br><br>-- <br>Hiroyuki Sato<br>