Kouhei Sutou
kou****@clear*****
2012年 6月 11日 (月) 16:25:53 JST
須藤です。 In <20120****@gmail*****> "[groonga-dev,00949] Re: rroonga での scoreの設定方法" on Mon, 11 Jun 2012 15:56:04 +0900, Shinya Kawaji <kawaj****@gmail*****> wrote: >> あ、これはですね、↓のようにするのが正しいです。 >> >> class ActiveGroonga::ResultSet >> def sort_by_shuffle(opts = {}) >> @records.select("_score = rand() && false", :syntax => :script) >> sort(["_score"], opts) >> end >> end > > 詳しく教えてくださり、ありがとうございます。 > > ただちょっと、上の書き方では以下の点が上手くいかないように思うのですが、 > 一般的にも再現する話でしょうか。 すみません。。。 >> @records.select("_score = rand() && false", :syntax => :script) の _score = rand() && false の部分は (_score = rand()) && false としなければいけませんでした。。。 (...)をつけないと _score = (rand() && false) というように解釈され_scoreがかならず0(= falseを数値にキャス トした値)になってしまいます。 なので、 > ■繰り返し行ってもランダムな値を返さない となっていました。 > ■Item.all.sort_by_shuffle と続けられない ... > all と select の両メソッドは、「絞り込みをするかしないか」くらいの違いし > か無いという認識だったのですが、なぜか all のほうは動作しませんでした。 実はもっと違いがあるのです。 selectの方は検索結果を格納するために一時的なテーブルを作成し てそこにヒットしたレコード(のID)を入れるのですが、allの方 はテーブルにあるすべてのレコードがヒットすることがすでにわかっ ているため、一時的なテーブルを作らないのです。 _scoreの格納場所は一時的なテーブルになるため、 sort_by_shuffleのケースではallではなくselectを使って一時的な テーブルを作成する必要があります。 [groonga-dev,00842]の↓が関連情報になります。 http://sourceforge.jp/projects/groonga/lists/archive/dev/2012-May/000842.html > groongaでは検索処理の結果を一時テーブル(*)に格納します。実 > は、_scoreカラムがあるのはSiteなどの永続的なテーブルではなく > 一時テーブルにあります。これは、永続的なテーブルに_scoreを追 > 加すると同時に複数の検索結果に_scoreをつけられないからです。 > 引数もブロックもないselectはこの一時テーブルを作っています。 > 何も条件を指定していないのですべてのレコードが格納されていま > す。 > > (*) 一時テーブルとはSiteなど名前がついていない、データベース > を閉じるとなくなってしまうテーブルのことです。 -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270) groongaサポート: http://groonga.org/ja/support/ プログラミングが好きなソフトウェア開発者を募集中: http://www.clear-code.com/recruitment/