5.7.1. ブーリアンモード — Mroonga vmrn_version documentation

本文へスキップ
`Ctrl`+`K`

# 5.7.1. ブーリアンモード

## 5.7.1.1. 概要

Mroongaは `MATCH AGAINST` に `IN 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 for` と `Mroonga for` はどちらも同じ結果を返します。

### 5.7.1.3.3. `+キーワード`

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

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

    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` から始まる単語（この場合は `MySQL` と `Mroonga` ）が含まれていること、という意味になります。:

    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 Profession` は `MySQL` という単語も `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 MODE` は `for` または `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 MODE` は `MySQL` と `Mroonga` の両方を含むという意味です。:

    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 MODE` は `MySQL` を含むが `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` は次の通りです。

> - `S`: スクリプト構文

#### 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 |
    -- +------------------------------------------------------------------------------+-------+

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

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