[groonga-dev,03210] Re: selectとin_valuesの制限事項について

Back to archive index

Kouhei Sutou kou****@clear*****
2015年 5月 8日 (金) 21:59:06 JST


須藤です。

In <CA+Tq****@mail*****>
  "[groonga-dev,03209] selectとin_valuesの制限事項について" on Fri, 8 May 2015 15:03:00 +0900,
  Hiroyuki Sato <hiroy****@gmail*****> wrote:

> 1, 質問事項
>   (1) selectの文字列の長さ上限
>      selectの文字列の長さに上限はありますか?

ありません。
リソース(メモリー)が許す限り長くできます。

ただし、文字列の長さの上限よりも前に↓のような他の上限に達す
ると思います。

>   (2) in_values(taget,value,value)のvalueの数の上限値

126個です。

メモ: GRN_SCAN_INFO_MAX_N_ARGSが128で0番目はprocedureオブジェ
クトになって、1番目はカラム(のインデックス)になるので、残
りの126が第2引数以降に使える数の限界。
TODO: ドキュメントに書いておく。

>   (3) in_valuesを使って全文検索のキーワードは指定できるか?

できません。

>     例えばチュートリアル: 4.10のCommentsテーブルの下記クエリを
>     in_valuesに変えることは可能でしょうか?
> 
>     select --table Comments \
>            --query 'comment:@NY OR comment:@tried' \
>            --output_columns _key,comment
> 
>     次のようにしたら結果が0になってしまいました。
>     select --table Comments \
>             --filter 'in_values(comment,"@NY","@tried")' \
>             --output_columns comment

in_valuesに変えることはできないのですが、--match_columnsに変え
ることはできます。--match_columnsを使うとこうなります。

  select --table Comments \
         --match_columns 'comment' \
         --query 'NY OR tried' \
         --output_columns _key,comment

>   (4) 下記案1以外の方法
>     下記案1以外の方法で良い方法はございますでしょうか?

後述するように、あります。

>     mroongaを使う等でも結構です。

今回のように込み入ったことをやるときは、Mroongaを使っていて
もGroongaの機能を使うことになるんですよねぇ。

> 2, やりたいこと
>    (1), 用語
>      (1-1) ユーザ: システムを利用する人
>      (1-2) キーワード: ユーザが興味を持っているキーワード
>        例) Groonga, rroonga, mysql等
>      (1-3) 記事
>        www.itmedia.co.jpなどに掲載される記事
> 
>    (2) やりたいこと
>     (2-1) ある記事Aに興味を持っているユーザを抽出する。
>      (2-2) 記事Aに興味を持っているかどうかは、各ユーザが持っている
>         キーワードが記事内に含まれているかを確認する。
> 
>    (3) 実現案1
>      (3-1) 実現方法
>       ・記事テーブル(Articles)を作って全文検索をできるようにする
>       ・selectでユーザ毎にキーワードを指定して全文検索をする
> 
>         select --table Articles \
>               --query 'text:キーワード1 OR text:キーワード2 OR ...' \
>               --output_columns _key,comment
> 
>     (3-3) 課題・懸念点
>       (a) in_values等を使ってもっと楽に検索条件を指定したい
> 
>    (b) キーワードの数多いと、文字列の上限に達してしまうのではないか?
> 
>   (c) できれば、なるべく少ない回数で、結果を抽出したい。
>    キーワードをユーザのベクターカラムに格納して、SQLのジョインの
>    ようなことをしたい

Groongaのクエリー(select)を考えるときのポイントは「どのテー
ブルのデータを入手したいか」を最初に考えることです。今回は

>     (2-1) ある記事Aに興味を持っているユーザを抽出する。

なので、最終的なselectは「select --table Users ...」という形
になります。あとは、この形になるように逆算していきます。

>      (2-2) 記事Aに興味を持っているかどうかは、各ユーザが持っている
>         キーワードが記事内に含まれているかを確認する。

なので、ユーザーを特定するには「記事内に含まれているキーワー
ド」で検索する必要があります。

ここで、

  ユーザー→キーワード→記事

ではなく

  記事→キーワード→ユーザー

という順に考え方を変えていることに注目してください。

ということで、最終的にはこんな感じになるはずです。

  select --table Users \
         --match_columns keywords \
         --query '記事内に含まれているキーワード1 OR 記事内に含まれているキーワード2 OR ...' \
         ...

あとは、「記事内に含まれているキーワード」を抽出できればよい
です。実は、それを実現する機能があります。

単語抽出演算子: http://groonga.org/ja/docs/reference/grn_expr/script_syntax.html#term-extract-operator

ということで、↓で「記事内に含まれているキーワード」を抽出で
きます。

  select --table Keywords \
         --filter '_key *T "記事の内容"'

(「記事の内容」を直接書くんじゃなくて
「Articles[key].content」とかで参照できるようにしたほうがよ
さそうですね。)

「記事の内容」を取得するために次のselectを実行する必要があり
ます。

  select --table Articles \
         --filter '_key == "XXX"' \
         --output_columns content


具体的なスキーマとデータとselectは次の通りです。

---
table_create Articles TABLE_HASH_KEY ShortText
column_create Articles content COLUMN_SCALAR Text

table_create Keywords TABLE_PAT_KEY ShortText \
  --normalizer NormalizerAuto
# 表示するときは正規化しない状態で表示したいならあると便利
# 例: 「groonga」ではなく「Groonga」と表示したい
# column_create Keywords label COLUMN_SCALAR ShortText

table_create Users TABLE_HASH_KEY ShortText
column_create Users keywords COLUMN_VECTOR Keywords


column_create Keywords users_keywords COLUMN_INDEX Users keywords


load --table Articles
[
{"_key": "article1", "content": "Groonga and Mroonga are good!"},
{"_key": "article2", "content": "MySQL and PostgreSQL are good!"},
{"_key": "article3", "content": "Groonga + MySQL = Mroonga!"}
]

load --table Users
[
{"_key": "user1", "keywords": ["Groonga", "MySQL"]},
{"_key": "user2", "keywords": ["MySQL"]},
{"_key": "user3", "keywords": ["Mroonga"]}
{"_key": "user4", "keywords": ["PostgreSQL"]}
]


select \
  --table Articles \
  --filter '_key == "article1"' \
  --output_columns content
# -> "Groonga and Mroonga are good!"

select \
  --table Keywords \
  --filter '_key *T "Groonga and Mroonga are good!"' \
  --output_columns _key
# -> ["groonga", "mroonga"]

select \
  --table Users \
  --match_columns keywords \
  --query 'groonga OR mroonga'
# -> [["user1", ["groonga", "mysql"]],
      ["user3", ["mroonga"]]]
---


-- 
須藤 功平 <kou****@clear*****>
株式会社クリアコード <http://www.clear-code.com/>

Groongaベースの全文検索システムを総合サポート:
  http://groonga.org/ja/support/
パッチ採用 - プログラミングが楽しい人向けの採用プロセス:
  http://www.clear-code.com/recruitment/
コードリーダー育成支援 - 自然とリーダブルコードを書くチームへ:
  http://www.clear-code.com/services/code-reader/




groonga-dev メーリングリストの案内
Back to archive index