株式会社クリアコード > ククログ

ククログ


Groongaの単語抽出演算子を使ったタグの付与

Groongaにはタグ検索という機能があります。

例えば、動画共有サイトであれば、登録されている動画に、その動画の特徴を表す短いキーワード(「スポーツ」、「カバディ」など)が含まれています。
これらの短いキーワードをタグといいます。
このタグで検索することで、動画のタイトルだけではなく、動画の特徴による検索ができ、より良い検索結果を提供できます。

上記の動画の例で言えば、動画のタイトルによる検索では自分が検索時に見たいと思った動画しか検索できませんが、タグ検索をすると、
検索時には意識していなかった興味のある動画を見つけることができます。

Groongaの公式ドキュメントの例は小規模なためデータにタグを人力で付与してデータを登録することができますが、実際に使用するケースではデータはもっと巨大です。
巨大なデータに人力でタグを付与するのは、とても困難な作業です。

データ登録時にユーザーにタグを指定してもらうインターフェースにするというのも解決策の一つです。
しかし、既にあるデータに対してタグ検索をしたいという要件が後から追加された場合は、上記の案では解決できません。
既に登録されたデータにタグとなるキーワードが含まれているかどうかを確認し、含まれているキーワードをタグとして登録する必要があります。
このような作業は人力ではなくコンピュータに任せたいところです。

Groongaでは、単語抽出演算子という演算子があり、これを使うことであらかじめ登録しておいた単語を抽出できます。
あらかじめタグとして使用するキーワードを登録しておき、タグを付与する対象のデータにこれらのキーワードが含まれていれば、そのキーワードを抽出できます。
したがって、この単語抽出演算子を使って抽出したキーワードをそのレコードのタグとして登録することで、検索用のタグを付与できます。

具体的には以下のように使用します。

まず、以下のようにタグとして抽出したいキーワードを_keyとして登録したテーブルを用意します。
抽出したいキーワードはテーブルのキーとして登録される必要があります。
また、抽出したいキーワードを登録するテーブルは、TABLE_PAT_KEYTABLE_DAT_KEYである必要があります。

以下の例では、Groonga, Mroonga, PGroonga, RroongaRuby, PostgreSQL, MySQL, Fulltextをタグとして使用するキーワードとして登録します。

table_create Words TABLE_PAT_KEY ShortText --normalizer NormalizerNFKC121
load --table Words
[
  {"_key": "Groonga"},
  {"_key": "Mroonga"},
  {"_key": "PGroonga"},
  {"_key": "Rroonga"},
  {"_key": "Ruby"},
  {"_key": "PostgreSQL"},
  {"_key": "MySQL"},
  {"_key": "Fulltext"}
]

単語抽出演算子の構文は_key *T "document"です。
documentの部分には、抽出対象のデータそのものをいれます。例えば、"Groonga is the successor project to Senna."という文書から上記で登録したキーワードを抽出したい場合は以下のようなクエリーを実行します。

select \
  --table Words \
  --filter '_key *T "Groonga is the successor project to Senna."' \
  --output_columns _key
[
  [
    0,
    1587435831.615494,
    0.003186702728271484
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "groonga"
      ]
    ]
  ]
]

この文書には、タグとして抽出したいキーワードのGroongaが含まれているので、上記のクエリーでGroongaが抽出されています。
抽出結果が"groonga"と小文字になっているのは、Wordsテーブルに指定しているNormalizerNFKC121がキーワードを正規化しているためです。
キーワードを正規化するのは、大文字/小文字の区別なくヒットさせるためです。
この抽出されたキーワードをタグとして登録します。

それではまず、説明のためタグを付与する前のデータを登録します。

table_create --name FullTextSearchEngines --flags TABLE_HASH_KEY --key_type UInt32
column_create --table FullTextSearchEngines --name name --flags COLUMN_SCALAR --type ShortText
column_create --table FullTextSearchEngines --name description --flags COLUMN_SCALAR --type ShortText

load --table FullTextSearchEngines
[
  {
    "_key":1,
    "name":"Groonga",
    "description":"Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of Groonga is that a newly registered document instantly appears in search results. Also, Groonga allows updates without read locks. These characteristics result in superior performance on real-time applications."
  },
  {
    "_key":2,
    "name":"Mroonga",
    "description":"Mroonga is a storage engine for MySQL. It provides fast fulltext search feature for all languages including Chinese, Japanese and Korean to all MySQL users. Mroonga was called Groonga storage engine"
  },
  {
    "_key":3,
    "name":"PGroonga",
    "description":"PGroonga is a PostgreSQL extension to use Groonga as the index.PostgreSQL supports full text search against languages that use only alphabet and digit. It means that PostgreSQL does not support full text search against Japanese, Chinese and so on. You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL!"
  },
  {
    "_key":4,
    "name":"Rroonga",
    "description":"Rroonga provides Groonga's DB-API layer features to Ruby. Features specialized to Web applications built on Rroonga are provided by ActiveGroonga. Convenience features for search Web applications are provided by racknga. All of them have the same merit that you can use Groonga features via Rubyish useful API. "
  },
  {
    "_key":5,
    "name":"Droonga",
    "description":"Droonga is a distributed full-text search engine, based on a stream oriented processing model. In many operations (searching, updating, grouping, and so on), Droonga processes various data by pipeline. As the result, Droonga has large potential around its flexibility and extensibility. Moreover, those features provide high availability for people who develop any data processing engine based on Droonga. You can process complex operations by mixing operations, and you can add custom operations to Droonga via plugins written as Ruby-scripts."
  }
]

上記の通り、全文検索エンジンの説明をデータとして登録しました。
nameが全文検索エンジンの名前、descriptionが全文検索エンジンの説明を表しています。
今回はこのdescriptionからキーワードを抽出して、タグとして書くレコードに付与します。

次は、単語抽出演算子を使ってタグとして使用するキーワードを抽出します。

select \
  --table Words \
  --filter '_key *T "Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of Groonga is that a newly registered document instantly appears in search results. Also, Groonga allows updates without read locks. These characteristics result in superior performance on real-time applications."' \
  --output_columns _key
[
  [
    0,
    1587436031.572823,
    0.001593351364135742
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "groonga"
      ]
    ]
  ]
]

select \
  --table Words \
  --filter '_key *T "Mroonga is a storage engine for MySQL. It provides fast fulltext search feature for all languages including Chinese, Japanese and Korean to all MySQL users. Mroonga was called Groonga storage engine"' \
  --output_columns _key
[
  [
    0,
    1587436162.267088,
    0.0009558200836181641
  ],
  [
    [
      [
        4
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "mroonga"
      ],
      [
        "mysql"
      ],
      [
        "fulltext"
      ],
      [
        "groonga"
      ]
    ]
  ]
]

select \
  --table Words \
  --filter '_key *T "PGroonga is a PostgreSQL extension to use Groonga as the index.PostgreSQL supports full text search against languages that use only alphabet and digit. It means that PostgreSQL does not support full text search against Japanese, Chinese and so on. You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL!"' \
  --output_columns _key
[
  [
    0,
    1587436237.72361,
    0.001041412353515625
  ],
  [
    [
      [
        3
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "pgroonga"
      ],
      [
        "groonga"
      ],
      [
        "postgresql"
      ]
    ]
  ]
]

select \
  --table Words \
  --filter '_key *T "Rroonga provides Groonga\'s DB-API layer features to Ruby. Features specialized to Web applications built on Rroonga are provided by ActiveGroonga. Convenience features for search Web applications are provided by racknga. All of them have the same merit that you can use Groonga features via Rubyish useful API. "' \
  --output_columns _key
[
  [
    0,
    1587436322.47859,
    0.0007700920104980469
  ],
  [
    [
      [
        3
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "rroonga"
      ],
      [
        "groonga"
      ],
      [
        "ruby"
      ]
    ]
  ]
]

select \
  --table Words \
  --filter '_key *T "Droonga is a distributed full-text search engine, based on a stream oriented processing model. In many operations (searching, updating, grouping, and so on), Droonga processes various data by pipeline. As the result, Droonga has large potential around its flexibility and extensibility. Moreover, those features provide high availability for people who develop any data processing engine based on Droonga. You can process complex operations by mixing operations, and you can add custom operations to Droonga via plugins written as Ruby-scripts."' \
  --output_columns _key
[
  [
    0,
    1587436396.106364,
    0.0008873939514160156
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_key",
          "ShortText"
        ]
      ],
      [
        "ruby"
      ]
    ]
  ]
]

これで各レコードが持つキーワードが抽出できました。
次は、抽出したキーワードをタグとして登録します。

以下では、既に作成したFullTextSearchEnginesテーブルにtagsカラムを追加しています。
tagsカラムはTagsテーブルへの参照になっており、Tagsテーブルは、tagsカラムに登録した文字列をキーとするレコードが作られます。
また、Tagsテーブルはtagsカラムに対するインデックスをindex_tagsカラムに格納してます。これにより、タグの全文検索を高速に実行できます。

table_create --name Tags --flags TABLE_HASH_KEY --key_type ShortText --normalizer NormalizerNFKC121
column_create --table FullTextSearchEngines --name tags --flags COLUMN_VECTOR --type Tags
column_create --table Tags --name index_tags --flags COLUMN_INDEX --type FullTextSearchEngines --source tags

load --table FullTextSearchEngines
[
  {
   "_key":1,
   "name":"Groonga",
   "description":"Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of Groonga is that a newly registered document instantly appears in search results. Also, Groonga allows updates without read locks. These characteristics result in superior performance on real-time applications.",
   "tags":,["groonga"]
  },
  {
    "_key":2,
    "name":"Mroonga","description":"Mroonga is a storage engine for MySQL. It provides fast fulltext search feature for all languages including Chinese, Japanese and Korean to all MySQL users. Mroonga was called Groonga storage engine",
    "tags":["mroonga" ,"mysql" ,"fulltext", "groonga"]
  },
  {
    "_key":3,
    "name":"PGroonga",
    "description":"PGroonga is a PostgreSQL extension to use Groonga as the index.PostgreSQL supports full text search against languages that use only alphabet and digit. It means that PostgreSQL does not support full text search against Japanese, Chinese and so on. You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL!",
    "tags":["pgroonga", "groonga", "postgresql"]
  },
  {
    "_key":4,
    "name":"Rroonga",
    "description":"Rroonga provides Groonga's DB-API layer features to Ruby. Features specialized to Web applications built on Rroonga are provided by ActiveGroonga. Convenience features for search Web applications are provided by racknga. All of them have the same merit that you can use Groonga features via Rubyish useful API."
    "tags":["rroonga","groonga", "ruby"]
  },
  {
    "_key":5,
    "name":"Droonga","description":"Droonga is a distributed full-text search engine, based on a stream oriented processing model. In many operations (searching, updating, grouping, and so on), Droonga processes various data by pipeline. As the result, Droonga has large potential around its flexibility and extensibility. Moreover, those features provide high availability for people who develop any data processing engine based on Droonga. You can process complex operations by mixing operations, and you can add custom operations to Droonga via plugins written as Ruby-scripts."
    "tags":["ruby"]
  }
]

これで、既存のデータにタグを付与し、タグ検索をする準備が整いました。
後は、以下のクエリーを実行すればタグによる検索が実行できます。

select --table FullTextSearchEngines --query tags:@Groonga --output_columns _key,name

上記では、Groongaというタグを持つレコードを検索しており、結果は以下のようになります。

[
  [
    0,
    1587436478.485265,
    0.002483844757080078
  ],
  [
    [
      [
        4
      ],
      [
        [
          "_key",
          "UInt32"
        ],
        [
          "name",
          "ShortText"
        ]
      ],
      [
        1,
        "Groonga"
      ],
      [
        2,
        "Mroonga"
      ],
      [
        3,
        "PGroonga"
      ],
      [
        4,
        "Rroonga"
      ]
    ]
  ]
]

無事にGroongaをタグに持つレコードが検索できました。

今回は、Groongaの単語抽出演算子を使って既存のデータにタグを付与してタグ検索をする方法を紹介しました。
既にあるデータにタグ検索機能を追加する場合には、この単語抽出機能の使用を検討してみてはいかがでしょうか。

タグ: Groonga
2020-04-21

«前の記事: ノータブルフィードバック8 - 要望が通らなかったときの振る舞い方 最新記事 次の記事: Gecko Embedded 68ESR対応 »
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|