須藤様<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&lt;<a href="mailto:kou****@clear*****">kou****@clear*****</a>&gt;さんは書きました:<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 &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;20150****@clear*****&#39;)">20150****@clear*****</a>&gt;<br>
  &quot;[groonga-dev,03210] Re: selectとin_valuesの制限事項について&quot; on Fri, 08 May 2015 21:59:06 +0900 (JST),<br>
  Kouhei Sutou &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;kou****@clear*****&#39;)">kou****@clear*****</a>&gt; wrote:<br>
<br>
&gt; select \<br>
&gt;   --table Keywords \<br>
&gt;   --filter &#39;_key *T &quot;Groonga and Mroonga are good!&quot;&#39; \<br>
&gt;   --output_columns _key<br>
&gt; # -&gt; [&quot;groonga&quot;, &quot;mroonga&quot;]<br>
&gt;<br>
&gt; select \<br>
&gt;   --table Users \<br>
&gt;   --match_columns keywords \<br>
&gt;   --query &#39;groonga OR mroonga&#39;<br>
&gt; # -&gt; [[&quot;user1&quot;, [&quot;groonga&quot;, &quot;mysql&quot;]],<br>
&gt; #     [&quot;user3&quot;, [&quot;mroonga&quot;]]]<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 &#39;sub_filter(keywords, &quot;_key *T \\&quot;Groonga and Mroonga are good!\\&quot;&quot;)&#39;<br>
# -&gt; [[&quot;user1&quot;, [&quot;groonga&quot;, &quot;mysql&quot;]],<br>
#     [&quot;user3&quot;, [&quot;mroonga&quot;]]]<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 &quot;...&quot;」の結果で絞り込んだ結果は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>
の条件を書かないといけないので「\」や「&quot;」のエスケープが必要<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>
{&quot;_key&quot;: &quot;article1&quot;, &quot;content&quot;: &quot;Groonga and Mroonga are good!&quot;},<br>
{&quot;_key&quot;: &quot;article2&quot;, &quot;content&quot;: &quot;MySQL and PostgreSQL are good!&quot;},<br>
{&quot;_key&quot;: &quot;article3&quot;, &quot;content&quot;: &quot;Groonga + MySQL = Mroonga!&quot;}<br>
]<br>
<br>
load --table Users<br>
[<br>
{&quot;_key&quot;: &quot;user1&quot;, &quot;keywords&quot;: [&quot;Groonga&quot;, &quot;MySQL&quot;]},<br>
{&quot;_key&quot;: &quot;user2&quot;, &quot;keywords&quot;: [&quot;MySQL&quot;]},<br>
{&quot;_key&quot;: &quot;user3&quot;, &quot;keywords&quot;: [&quot;Mroonga&quot;]}<br>
{&quot;_key&quot;: &quot;user4&quot;, &quot;keywords&quot;: [&quot;PostgreSQL&quot;]}<br>
]<br>
<br>
<br>
select \<br>
  --table Articles \<br>
  --filter &#39;_key == &quot;article1&quot;&#39; \<br>
  --output_columns content<br>
# -&gt; &quot;Groonga and Mroonga are good!&quot;<br>
<br>
select \<br>
  --table Keywords \<br>
  --filter &#39;_key *T &quot;Groonga and Mroonga are good!&quot;&#39; \<br>
  --output_columns _key<br>
# -&gt; [&quot;groonga&quot;, &quot;mroonga&quot;]<br>
<br>
select \<br>
  --table Users \<br>
  --filter &#39;sub_filter(keywords, &quot;_key *T \\&quot;Groonga and Mroonga are good!\\&quot;&quot;)&#39;<br>
# -&gt; [[&quot;user1&quot;, [&quot;groonga&quot;, &quot;mysql&quot;]],<br>
#     [&quot;user3&quot;, [&quot;mroonga&quot;]]]<br>
---<br>
<br>
<br>
--<br>
須藤 功平 &lt;<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;kou****@clear*****&#39;)">kou****@clear*****</a>&gt;<br>
株式会社クリアコード &lt;<a href="http://www.clear-code.com/" target="_blank">http://www.clear-code.com/</a>&gt;<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, &#39;cvml&#39;, &#39;groon****@lists*****&#39;)">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>