全文検索とキーワードスコアリング方式のMySQL実装例

全文検索とキーワードスコアリング方式のMySQL実装例

1. はじめに

今日、同僚から、MySQL を使用して ElasticSearch に似た全文検索機能を実装し、検索キーワードにスコアを付ける方法を尋ねられました。すぐに私の心の中に疑問が浮かびました。なぜesを使わないのですか?シンプルで使いやすく、高速です。しかし、データ量が多くなく、クライアントから与えられた時間も非常に限られており、esを構築する時間がないとのことなので、MySQLの全文検索機能を見てみましょう!

MySQL バージョン 5.7.6 以降では、中国語、日本語、韓国語の単語分割をサポートする ngram フルテキスト パーサーが組み込まれています。 MySQL 5.7.6 より前のバージョンでは、フルテキスト インデックスは英語のフルテキスト インデックスのみをサポートしており、中国語のフルテキスト インデックスはサポートしていませんでした。単語セグメンターを使用して中国語の段落を単語に前処理し、データベースに保存する必要がありました。この記事は、Mysql 5.7.6、InnoDB データベース エンジンを使用してテストされました。 mysql 全文検索

2. 全文パーサーngram

ngram は、テキスト内の n 個の連続した単語のシーケンスです。 ngram フルテキスト パーサーは、テキストを単語に分割できます。各単語は n 個の連続した単語のシーケンスです。
たとえば、ngram フルテキスト パーサーを使用して「hello world」をトークン化します。

n=1: 「あなた」、「良い」、「世界」、「世界」 
n=2: 「こんにちは」、「良い世界」、「世界」 
n=3: 「こんにちは世界」、「良い世界」 
n=4: 「こんにちは世界」

MySQL はグローバル変数 ngram_token_size を使用して、ngram 内の n のサイズを設定します。値の範囲は 1 ~ 10 で、デフォルト値は 2 です。通常、ngram_token_size はクエリされる単語の最小数に設定されます。単語のみを検索する必要がある場合は、ngram_token_size を 1 に設定します。デフォルト値 2 の場合、単語 1 つを検索しても結果は返されません。中国語の単語は少なくとも 2 つの文字で構成されているため、デフォルト値の 2 が推奨されます。

MySQL のデフォルトの ngram_token_size を見てみましょう。

'ngram_token_size' のような変数を表示する

ngram_token_size 変数を設定するには、次の 2 つの方法があります。

1. mysqldコマンドの起動時に指定する

mysqld --ngram_token_size=2

2. MySQL設定ファイルを変更する

[mysqld] 
nグラムトークンサイズ=2

3. 全文索引

ドキュメントデータを例にとると、新しいデータテーブル t_wenshu が作成され、ドキュメントコンテンツフィールドにフルテキストインデックスが作成され、100,000 件のテストデータがインポートされます。

1. テーブルを構築するときにフルテキストインデックスを作成する

テーブル `t_wenshu` を作成します (
 `province` varchar(255) デフォルト NULL,
 `caseclass` varchar(255) デフォルト NULL,
 `casenumber` varchar(255) デフォルト NULL,
 `caseid` varchar(255) デフォルト NULL,
 `types` varchar(255) デフォルト NULL,
 `title` varchar(255) デフォルト NULL,
 `content` 長文、
 `updatetime` varchar(255) デフォルト NULL,
 フルテキストキー `content` (`content`) とパーサー `ngram`
)ENGINE=InnoDB デフォルト文字セット=utf8;

2. テーブル変更方法

ALTER TABLE t_wenshu に、PARSER ngram を使用して FULLTEXT INDEX content_index (content) を追加します。

3. インデックス作成メソッドを通じて

PARSER ngram を使用して、t_wenshu (content) にフルテキスト インデックス content_index を作成します。

4. 検索モード

自然言語検索

(自然言語モード) 自然言語モードは、MySQL のデフォルトの全文検索モードです。自然言語モードでは演算子を使用できず、キーワードが表示される必要がある、または表示されない必要があるなどの複雑なクエリを指定することはできません。

ブール検索

(ブール モード) 一致する行の半分以上に出現する単語を除外します。たとえば、すべての行に「this」という単語が含まれている場合、「this」で検索しても結果は見つかりません。これは、レコードの数が多い場合に非常に便利です。データベースは、すべての行を検索しても意味がないと判断するためです。この場合、「this」はほぼストップワードと見なされます。ブール検索モードで演算子を使用すると、キーワードの出現または不出現の指定、キーワードの重みが高いか低いかの指定など、複雑なクエリをサポートできます。

● ブールモードの機能:
一致基準が 50% を超える行は削除しないでください。
関連性の逆順に自動的に並べ替えることはありません。
FULLTEXT インデックスなしでフィールドを検索することも可能ですが、非常に遅くなります。
·最大および最小の文字列を制限します。
· ストップワードを適用します。

● 検索構文ルール:
+ 存在する必要があります (このキーワードを含まないデータ エントリは無視されます)。
- 許可されません (指定されたキーワードを除き、そのキーワードを含むすべてのエントリは無視されます)。
> この一致するデータの重みを増やします。
< 一致するデータの重みを減らします。
~ は相関関係を正から負に変えることにより、その単語があると相関関係が減少することを示します (ただし、その単語を除外する like は除きます)。順位が下がり、重みが低くなるだけです。
* ワイルドカードは、先頭に配置される他の構文とは異なり、文字列の後に配置する必要があります。
" " 二重引用符を使用して文を囲むと、元の文と完全に一致する必要があり、文字を分離できないことを示します。

クエリ拡張検索

注意: (クエリ拡張あり) クエリ拡張により無関係なクエリが多数生成される可能性があるため、注意して使用してください。

5. 検索クエリ

1) コンテンツに「盗難」を含むレコードをクエリします。クエリステートメントは次のとおりです。

t_wenshu から caseid、content、MATCH (content) AGAINST ('Theft') をスコアとして選択します。MATCH (content) AGAINST ('Theft' IN NATURAL LANGUAGE MODE)

2) コンテンツに「挑交惹事」を含むレコードを検索します。クエリステートメントは次のとおりです。

select caseid,content, MATCH (content) AGAINST ('寻怨惹事') as score from t_wenshu where MATCH (content) AGAINST ('寻怨惹事' IN NATURAL LANGUAGE MODE);

3) 単一の漢字、コンテンツに「我」を含むレコードを検索する場合、クエリステートメントは次のとおりです。

t_wenshu から caseid、content、MATCH ( content) AGAINST ('我') をスコアとして選択します。ここで、MATCH ( content) AGAINST ('我' IN NATURAL LANGUAGE MODE) ;

注: グローバル変数 ngram_token_size の値が 2 に設定されているためです。単一の中国語文字をクエリする場合は、構成ファイル my.ini で ngram_token_size = 1 を変更し、mysqld サービスを再起動する必要があります。ここではこれを試しません。

4) クエリフィールドの内容には、次のように「危険運転」と「喧嘩やトラブルを起こす」が含まれています。

select caseid,content, MATCH (content) AGAINST ('+危険運転+けんかを売ってトラブルを起こす') as score from t_wenshu where MATCH (content) AGAINST ('+危険運転+けんかを売ってトラブルを起こす' IN BOOLEAN MODE);

5) クエリフィールドの内容には、「危険運転」は含まれていますが、「喧嘩を売ったりトラブルを起こしたりすること」は含まれていません。

select caseid,content, MATCH (content) AGAINST ('+危険運転-喧嘩を売ってトラブルを起こす') as score from t_wenshu where MATCH (content) AGAINST ('+危険運転-喧嘩を売ってトラブルを起こす' IN BOOLEAN MODE);

6) クエリフィールドの内容には、次のように「危険運転」または「口論やトラブルを起こす」が含まれます。

select caseid,content, MATCH (content) AGAINST ('危険運転とトラブル誘発') as score from t_wenshu where MATCH (content) AGAINST ('危険運転とトラブル誘発' IN BOOLEAN MODE);

VI. 結論

1) MySQL フルテキスト インデックスを使用する前に、各バージョンのサポート状況を確認してください。

2) 全文インデックスは like + % よりも N 倍高速ですが、精度の問題が発生する可能性があります。

3) 大量のデータを完全にインデックス化する必要がある場合は、まずデータを追加してからインデックスを作成することをお勧めします。

4) 中国語の場合、MySQL 5.7.6 以降のバージョン、または Sphinx や Lucene などのサードパーティ製プラグインを使用できます。

5) MATCH() 関数で使用されるフィールド名は、フルテキスト インデックスの作成時に指定されたフィールド名と一致している必要があり、同じテーブルのフィールドのみにすることができ、テーブルをまたぐことはできません。

これで、MySQL の全文検索とキーワード スコアリングに関するこの記事は終了です。MySQL の全文検索とキーワード スコアリングに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL 5.7 での中国語全文検索の詳細な分析
  • MySQL フルテキスト検索の中国語ソリューションとサンプルコード
  • MySQL全文検索の使用例
  • MySQL 5.7.25 全文検索チュートリアル

<<:  JavaScript における一般的な配列操作

>>:  UbuntuはSSHサービスのリモートログイン操作を開始します

推薦する

Nginx ロケーションマッチングルールの例

1. 文法 場所 [=|~|~*|^~|@] /uri/ { ... } 2. 説明上記の構文から、...

Linux 7.6 バイナリに MySQL 8.0.27 をインストールする詳細な手順

目次1. 環境整備1.1 オペレーティング システムのバージョン1.2 ディスク容量1.3 ファイア...

MacでのMySQL5.7.22のインストール手順

1. インストールパッケージを使用してMySQLをインストールします(オンラインダウンロードは遅すぎ...

Linux deb パッケージの解凍、変更、その他の操作方法のコード例

さまざまな理由により、debパッケージ内のさまざまなファイルの内容を直接変更する必要がある場合があり...

jQuery+h5 で 9 マス抽選特殊効果を実現 (フロントエンドとバックエンドのコード)

序文:フロントエンド: jq+h5 で 9 グリッドのダイナミック効果を実現バックエンド: thin...

SQL文でのgroup byの使用について簡単に説明します

1. 概要Group by は、by の後の規則に従ってデータをグループ化することを意味します。いわ...

MySQL マスタースレーブレプリケーションの実践の詳細説明 - ログポイントに基づくレプリケーション

ログポイントベースのレプリケーション1. マスターデータベースとスレーブデータベースに専用のレプリケ...

Websocket に基づくシンプルなチャットルームダイアログの実装

この記事では、WebSocketを使用して簡単なチャットルームの会話を実装するための具体的なコードを...

モバイルアダプティブスタイルで@mediaを使用する方法

一般的な携帯電話のスタイル: @media all および (orientation : 縦向き) ...

{{ }} で関数を直接使用する WeChat アプレットの例

序文WeChat アプレット開発 (ネイティブ wxml、wxcss) で、{{ }} 内で直接メソ...

CSSで検索ボックスを非表示にする機能を実装します(アニメーション順方向と逆方向のシーケンス)

上部のメニュー バーに検索ボックスを配置するのは一般的なシナリオですが、検索機能がそれほど頻繁に使用...

画像をクリックして切り替えるJavaScript

クリックして画像を切り替えることは、日常生活で非常によく行われることです。今日の練習は、画像を切り替...

Reactでのイベントバインディングの実装は3つの方法を指しています

1. 矢印関数1. 矢印関数自体はこれをバインドしないという事実を利用します。 2. render(...

RHCEはApacheをインストールし、ブラウザでIPにアクセスします

1. at は、5 時間後にルート ディレクトリの at_test ファイルに「これは at タスク...

MySQL クエリ データベース容量方法手順

すべてのデータベースの合計サイズを照会する方法は次のとおりです。 mysql> informa...