5.7.1. ブーリアンモード#

5.7.1.1. 概要#

Mroongaは MATCH AGAINSTIN BOOLEAN MODE 修飾子をつけることでブーリアン全文検索を実行できます。:

SELECT ... WHERE MATCH(column) AGAINST ('...' IN BOOLEAN MODE);

通常、デフォルトの IN NATURAL LANGUAGE MODE よりも IN BOOLEAN MODE の方が適切です。なぜなら IN BOOLEAN MODE はWeb検索エンジンのクエリーと似ているからです。多くのユーザーはWeb検索エンジンのクエリーに慣れています。

ブーリアン全文検索のクエリーでは MySQLがサポートしている修飾子 とMroonga独自のプラグマを使うことができます。

この修飾子とプラグマで検索結果の順位を変更できます。

修飾子もプラグマもどちらも使わずに検索した場合、検索キーワードをより多く含むレコードの方が順位が高くなります。

5.7.1.2. 使いかた#

以下は例を示すためのスキーマとデータです。:

CREATE TABLE books (
  `id` INTEGER AUTO_INCREMENT,
  `title` text,
  PRIMARY KEY(`id`),
  FULLTEXT INDEX title_index (title)
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;

INSERT INTO books (title) VALUES ('Professional MySQL');
INSERT INTO books (title) VALUES ('MySQL for Professional');
INSERT INTO books (title) VALUES ('Mroonga = MySQL + Groonga');

5.7.1.3. 修飾子#

サポートしている修飾子は次の通りです。

5.7.1.3.1. キーワード1 キーワード2#

キーワード1 キーワード2 のようにキーワードの間に演算子がない場合は、指定したキーワードのどれかひとつでも含まれていればヒット、という検索条件になります。

Mroonga for というクエリーは Mroonga または for が含まれているという意味です。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('Mroonga for' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- | MySQL for Professional    |
-- +---------------------------+

5.7.1.3.2. キーワード1 OR キーワード2#

OR (大文字にすること)は左辺のキーワードまたは右辺のキーワードのうち少なくともどちらか1つは含まれていること、という意味です。

Mroonga OR for というクエリーは Mroonga または for が含まれているという意味です。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('Mroonga OR for' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- | MySQL for Professional    |
-- +---------------------------+

OR はデフォルトの演算子です。省略可能です。 Mroonga OR forMroonga for はどちらも同じ結果を返します。

5.7.1.3.3. +キーワード#

キーワードの前に「+」をつけると、そのキーワードは必ず含まれていること、という検索条件になります。

+MySQL +Mroonga というクエリーは MySQLMroonga もどちらも含まれていること、という意味になります。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('+MySQL +Groonga' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- +---------------------------+

5.7.1.3.4. -キーワード#

キーワードの前に「-」をつけると、そのキーワードは含まれないこと、という検索条件になります。

+MySQL -Mroonga というクエリーは MySQL は含まれるけど Mroonga は含まれないという意味になります。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('+MySQL -Mroonga' IN BOOLEAN MODE);
-- +------------------------+
-- | title                  |
-- +------------------------+
-- | Professional MySQL     |
-- | MySQL for Professional |
-- +------------------------+

5.7.1.3.5. プレフィックス*#

プレフィックスの後に「*」をつけると、そのプレフィックスの単語を含むこと、という検索条件になります。

+M* というクエリーは M から始まる単語(この場合は MySQLMroonga )が含まれていること、という意味になります。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('+M*' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- | Professional MySQL        |
-- | MySQL for Professional    |
-- +---------------------------+

注釈

正確に言うと、「単語」はあなたが思っている「単語」ではないかもしれません。この文脈での「単語」は「トークン」ということです。「トークン」は単語ではないかもしれません。たとえば、「It's」の中のトークンは「It」と「'」と「s」です。

mroonga_command()tokenize を使うとトークンを確認できます。:

SELECT mroonga_command('tokenize TokenBigram "It''s" NormalizerMySQLGeneralCI');
-- +--------------------------------------------------------------------------+
-- | mroonga_command('tokenize TokenBigram "It''s" NormalizerMySQLGeneralCI') |
-- +--------------------------------------------------------------------------+
-- | [                                                                        |
-- |   {                                                                      |
-- |     "value":"IT",                                                        |
-- |     "position":0,                                                        |
-- |     "force_prefix":false                                                 |
-- |   },                                                                     |
-- |   {                                                                      |
-- |     "value":"'",                                                         |
-- |     "position":1,                                                        |
-- |     "force_prefix":false                                                 |
-- |   },                                                                     |
-- |   {                                                                      |
-- |     "value":"S",                                                         |
-- |     "position":2,                                                        |
-- |     "force_prefix":false                                                 |
-- |   }                                                                      |
-- | ]                                                                        |
-- +--------------------------------------------------------------------------+

上の結果のJSONの値は手で整形しています。

5.7.1.3.6. "フレーズ"#

ダブルクォート( " )でフレーズを囲むと、そのフレーズが必ず含まれていること、という検索条件になります。

+"Professional MySQL" というクエリーは Professional MySQL というフレーズが含まれていること、という意味になります。このクエリーは MySQL for Profession にはマッチしません。 MySQL for ProfessionMySQL という単語も Professional という単語も含んでいますが、 Professional MySQL というフレーズは含んでいません。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('+"Professional MySQL"' IN BOOLEAN MODE);
-- +--------------------+
-- | title              |
-- +--------------------+
-- | Professional MySQL |
-- +--------------------+

5.7.1.3.7. (サブ式...)#

カッコを使うと式をグルーピングできます。

+(Groonga OR Mroonga) +MySQL というクエリーは次のような意味です。

  • Groonga あるいは Mroonga のどちらかが含まれている。

  • MySQL が含まれている。

以下はこのクエリーの実行結果です。:

SELECT title
  FROM books
 WHERE MATCH(title) AGAINST('+(Groonga OR Mroonga) +MySQL' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- +---------------------------+

5.7.1.4. プラグマ#

プラグマはクエリーのメタデータです。プラグマを指定することでクエリーのパース方法を変更できます。

実行方法をカスタマイズするためにクエリーの先頭にプラグマを埋め込むことができます。

プラグマはクエリーの先頭になければいけません。クエリーの先頭に空白を入れてはいけません。プラグマは * から始まります。:

SELECT MATCH AGAINST('*PRAGMA ...' IN BOOLEAN MODE);

複数のプラグマを指定することができます。:

SELECT MATCH AGAINST('*PRAGMA1PRAGMA2 ...' IN BOOLEAN MODE);

以下は利用可能なプラグマの一覧です。

5.7.1.4.1. D プラグマ#

D プラグマはデフォルトの演算子を指定します。個別の演算子を省略するとデフォルトの演算子を使います。

D プラグマの構文は次の通りです。 ${OPERATOR} には OR または + または - を指定します。:

*D${OPERATOR}

5.7.1.4.1.1. DOR#

DOR はデフォルトの演算子として「OR」を使うという意味です。

これがデフォルトです。

DOR を使う例は次の通りです。 '*DOR for Mroonga' IN BOOLEAN MODEfor または Mroonga を含むという意味です。

SELECT title
 FROM books
WHERE MATCH (title) AGAINST('*DOR for Mroonga' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | MySQL for Professional    |
-- | Mroonga = MySQL + Groonga |
-- +---------------------------+

5.7.1.4.1.2. D+#

D+ はデフォルトの演算子として「AND」を使うという意味です。これはWeb検索エンジンのクエリーと同じ挙動です。

D+ を使う例は次の通りです。 '*D+ MySQL Mroonga' IN BOOLEAN MODEMySQLMroonga の両方を含むという意味です。:

SELECT title
 FROM books
WHERE MATCH (title) AGAINST('*D+ MySQL Mroonga' IN BOOLEAN MODE);
-- +---------------------------+
-- | title                     |
-- +---------------------------+
-- | Mroonga = MySQL + Groonga |
-- +---------------------------+

5.7.1.4.1.3. D-#

D- はデフォルトの演算子として「NOT」を使うという意味です。

D- を使う例は次の通りです。 '*D- MySQL Mroonga' IN BOOLEAN MODEMySQL を含むが Mroonga を含まないという意味です。:

SELECT title
 FROM books
WHERE MATCH (title) AGAINST('*D- MySQL Mroonga' IN BOOLEAN MODE);
-- +------------------------+
-- | title                  |
-- +------------------------+
-- | Professional MySQL     |
-- | MySQL for Professional |
-- +---------------------------+

5.7.1.4.2. W プラグマ#

W プラグマはマルチカラムインデックス用のプラグマです。検索対象のセクションとその重みを指定します。

各セクションごとに違う重みを指定できます。デフォルトの重みは 1 です。 1 は重みがないという意味です。

W プラグマの構文は次の通りです。 ${SECTION} は0ではなく1から始まる数値です。 ${WEIGHT} は省略可能です。:

*W[${SECTION1}[:${WEIGHT1}]][,${SECTION2}[:${WEIGHT2}]][,...]

次は例を示すためのスキーマとデータです。 W プラグマを使うためにはマルチカラムインデックスを作る必要があります。:

CREATE TABLE memos (
  `id` INTEGER AUTO_INCREMENT,
  `title` text,
  `content` text,
  PRIMARY KEY(`id`),
  FULLTEXT INDEX text_index (title, content)
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;

INSERT INTO memos (title, content) VALUES (
  'MySQL', 'MySQL is a RDBMS.'
);
INSERT INTO memos (title, content) VALUES (
  'Groonga', 'Groonga is a full text search engine.'
);
INSERT INTO memos (title, content) VALUES (
  'Mroonga', 'Mroonga is a storage engine for MySQL based on Groonga.'
);

次の例は重みの使い方を示す例です。 title カラムは重みが 10 で、 content カラムは重みが 1 です。これは title カラムの中にあるキーワードは content カラムの中にあるキーワードよりも10倍重要だということです。

SELECT title,
       content,
       MATCH (title, content) AGAINST('*W1:10,2:1 +Groonga' IN BOOLEAN MODE) AS score
  FROM memos;
-- +---------+--------------------------------------------------------+-------+
-- | title   | content                                                | score |
-- +---------+--------------------------------------------------------+-------+
-- | MySQL   | MySQL is a RDBMS.                                      |     0 |
-- | Groonga | Groonga is a full text search engine.                  |    11 |
-- | Mroonga | Mroonga is a storage engine for MySQL based on Groonga |     1 |
-- +---------+--------------------------------------------------------+-------+

最初のレコードのスコアーは 0 です。なぜなら、 title カラムにも content カラムにも Groonga が含まれていないからです。

二つめのレコードのスコアーは 11 です。なぜなら、 title カラムにも content カラムにもどちらにも Groonga が含まれているからです。 title カラム内の Groonga のスコアーは 10 です。 content カラム内の Groonga のスコアーは 1 です。 11 はこれらのスコアーの合計値です。

三つめのレコードのスコアーは 1 です。なぜなら、 content カラムにだけ Groonga が含まれているからです。 content カラムの Groonga のスコアーは 1 です。そのため、このレコードのスコアーは 1 になります。

5.7.1.4.3. S プラグマ#

S プラグマはクエリーの構文を指定します。

S プラグマの構文は次の通りです。:

*S${SYNTAX}

利用可能な syntax は次の通りです。

5.7.1.4.3.1. *SS#

*SS プラグマを使うと スクリプト構文 を使えます。スクリプト構文ではGroongaのすべての検索機能を使えます。

以下はスクリプト構文の使い方を示す例のためのスキーマとデータです。:

CREATE TABLE comments (
  `content` text,
  FULLTEXT INDEX content_index (content)
) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4;

INSERT INTO comments VALUES (
  'A student started to use Mroonga storage engine. It is very fast!'
);
INSERT INTO comments VALUES (
  'Another student also started to use Mroonga storage engine. It is very fast!'
);

以下はスクリプト構文で 近傍検索 を使う例です。:

SELECT content,
       MATCH (content) AGAINST('*SS content *N "student fast"' IN BOOLEAN MODE) AS score
  FROM comments;
-- +------------------------------------------------------------------------------+-------+
-- | content                                                                      | score |
-- +------------------------------------------------------------------------------+-------+
-- | A student started to use Mroonga storage engine. It is very fast!            |     1 |
-- | Another student also started to use Mroonga storage engine. It is very fast! |     0 |
-- +------------------------------------------------------------------------------+-------+

近傍検索は指定した単語間(今回の場合は studentfast )に10単語以下しかない場合のみマッチします。そのため、 student started ...(8単語)... very fast はマッチしますが、 student also started ...(8単語)... very fast はマッチしません。

他の上級者向け機能も使えます。