MySQL でシンプルな検索エンジンを実装するためのサンプルコード

MySQL でシンプルな検索エンジンを実装するためのサンプルコード

序文

以前、プロジェクトの要件により、キーワードに基づいてチャット記録を検索する必要がありました。これは検索エンジンの機能ではないでしょうか?

そこで最初に思いついたのがElasticSearch分散検索エンジンだったのですが、何らかの理由で会社のサーバーリソースが比較的逼迫しており、ElasticSearchサービスを展開するための余分なマシンがありませんでした。また、オンライン時間も比較的逼迫しており、データ量もそれほど多くありませんでした。そこで、MySQLの全文インデックスを思いつきました。

導入

実際、MySQL は長い間フルテキスト インデックスをサポートしてきましたが、サポートされていたのは英語の検索のみでした。バージョン 5.7.6 以降、MySQL には中国語、日本語、韓国語の単語分割をサポートする ngram フルテキスト パーサーが組み込まれています。

Mysql フルテキスト インデックスは、転置インデックスの原理を採用しています。転置インデックスでは、キーワードが主キーとなり、各キーワードはキーワードが出現する一連のファイルに対応します。このように、ユーザーがキーワードを検索すると、ソート プログラムは逆インデックス内でキーワードを見つけ、そのキーワードを含むすべてのファイルをすぐに見つけることができます。

この記事はMySQL 8.0に基づいてテストされており、データベースエンジンはInnoDBを使用しています。

ngram全文パーサー

ngram は、テキスト内の n 個の連続した単語のシーケンスです。 ngram フルテキスト パーサーは、各単語が n 個の連続した単語のシーケンスであるテキストをトークン化できます。たとえば、ngram フルテキスト パーサーを使用して「你好靓仔」をセグメント化します。

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 構成ファイル my.ini を変更し、最後にパラメータの行を追加します。

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

全文インデックスを作成する

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

テーブル「記事」を作成します(
  `id` bigint NOT NULL、
  `url` varchar(1024) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  `title` varchar(256) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  `source` varchar(32) COLLATE utf8mb4_general_ci DEFAULT ''
  `keywords` varchar(32) COLLATE utf8mb4_general_ci デフォルト NULL,
  `publish_time` タイムスタンプ NULL デフォルト NULL、
  主キー (`id`)、
  フルテキストキー `title_index` (`title`) とパーサー `ngram`
) エンジン=InnoDB デフォルト文字セット=utf8mb4 照合=utf8mb4_general_ci;

2. テーブル変更方法

ALTER TABLE article に FULLTEXT INDEX title_index(title) を追加し、PARSER ngram を追加します。

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

PARSER ngram を使用して article (title) に FULLTEXT インデックス title_index を作成します。

検索方法

1. 自然言語検索(自然言語モード)

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

select * from article where MATCH(title) AGAINST ('北京観光' IN NATURAL LANGUAGE MODE);

// モードが指定されていない場合は、デフォルトで自然言語モードが使用されます select * from article where MATCH(title) AGAINST ('北京旅游'); 

このモードでは、「北京 旅行」を検索すると、自然言語に基づいて 2 つのキーワードに分割されるため、「北京」または「旅行」を含むコンテンツを検索できることがわかります。

上記の例では、返される結果は一致度によって自動的にソートされ、最も一致度が高いものが先頭に表示されます。一致度は、負でない浮動小数点数です。

// 一致度を確認します。select *、MATCH(title) AGAINST ('Beijing Tourism') as score from article where MATCH(title) AGAINST ('Beijing Tourism' IN NATURAL LANGUAGE MODE); 

2. ブール検索(ブールモード)

ブール検索モードでは、演算子を使用して、キーワードが表示される必要があるか表示されない必要があるか、キーワードの重みが高いか低いかを指定するなどの複雑なクエリをサポートできます。

// 演算子なし // 「デート」または「戦略」を含む
select * from article where MATCH(title) AGAINST ('Dating Guide' IN BOOLEAN MODE); 

// 演算子を使用する // 「デート」を含める必要がありますが、「戦略」を含めることができます
select * from article where MATCH(title) AGAINST ('+Dating Guide' IN BOOLEAN MODE); 

その他の演算子の例:

「デートのヒント」 
演算子なし、OR を意味し、「デート」または「戦略」のいずれかを含む

「+デート+戦略」
「+デートのヒント」という単語の両方を含める必要があります
「デート」が含まれている必要がありますが、「戦略」も含まれている場合は一致率が高くなります。

「+デート戦略」
「日付」を含める必要があり、「戦略」を含めることはできません。

「+デート〜戦略」
「デート」は必ず含める必要がありますが、「戦略」も含めると、一致スコアは「戦略」なしの記録よりも低くなります。

'+デート+(>戦略<ヒント)'
クエリには、「デート」と「戦略」または「デート」と「スキル」のレコードが含まれている必要がありますが、「デート戦略」は「デートスキル」よりも一致率が高くなります。

「デート*」
クエリには、「Appointment」で始まるレコードが含まれます。

「デートのヒント」
検索する単語を二重引用符で囲みます。効果は「%Dating Guide%」のようになります。
たとえば、「初心者向けのデート戦略」は一致しますが、「デート戦略」は一致しません。

比較する

同様のクエリと比較して、フルテキスト インデックスには次の利点があります。

  • LIKE はあいまい一致のみを実行しますが、フルテキスト インデックスはいくつかの文法および意味クエリ機能を提供し、MySQL ボキャブラリによって決定される検索対象の文字列に対して単語分割操作を実行します。
  • 全文インデックスでは、単語の最小長と最大長、および無視する単語を設定できます。これらはすべて設定可能です。
  • フルテキスト インデックスを使用して列内の文字列を検索すると、一致するキーワードの数として理解できる一致度が返され、これは浮動小数点数です。

全文検索のパフォーマンスは類似クエリよりも優れています

以下は約50wのデータに基づいたテストです。

// クエリのように select * from article where title like '%北京%'; 

// フルテキスト インデックス クエリ select * from article where MATCH(title) AGAINST ('北京' IN BOOLEAN MODE); 

類似クエリは 1.536 秒、全文インデックス クエリは 0.094 秒と、約 16 倍高速であることがわかります。

要約する

全文インデックスを使用すると高速な検索が可能になりますが、インデックスを維持するためのオーバーヘッドも発生します。フィールドの長さが長くなるほど、作成されるフルテキスト インデックスが大きくなり、DML ステートメントのスループットに影響します。データ量が多くない場合は、フルテキストインデックスを使用して検索できます。これは簡単で便利です。ただし、データ量が多い場合は、専用の検索エンジン ElasticSearch を使用して検索することをお勧めします。

MySQL で簡単な検索エンジンを実装するためのサンプルコードに関するこの記事はこれで終わりです。MySQL 検索エンジンに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL全文インデックスを使用して検索エンジンのサンプルコードの簡易版を実現する
  • MySQL ベースの検索エンジンである MySQL-Fulltext の詳細な紹介
  • Scrapy+flask+htmlで検索エンジンのサンプルコードを作成する
  • Pythonは検索エンジンをベースに記事重複チェック機能を実装
  • Python 実践的な手書き検索エンジン
  • Python大規模検索エンジン画像クローラーツールの詳細説明
  • 360 検索エンジン自動組み込み PHP 書き換えソリューション
  • 検索エンジンのクロール記録を記録するための PHP 実装コード
  • Python ロスレス音楽検索エンジン実装コード
  • MySQL をベースにしたシンプルな検索エンジンを実装する

<<:  JSの高階関数5つを共有する

>>:  Dockerにlogstashをインストールする詳細な手順

ブログ    

推薦する

JSの矢印関数におけるこのポイントの詳細な説明

矢印関数は ES6 の新機能です。独自の this はありません。その this ポイントは外部のコ...

MySQL 8.0.15 インストール グラフィック チュートリアルとデータベースの基礎

MySQLソフトウェアのインストールとデータベースの基礎は参考用です。具体的な内容は次のとおりです。...

MySQL 日付処理関数の例の分析

この記事は主にMySQLの日付処理関数のサンプル分析を紹介します。この記事ではサンプルコードを詳細に...

UbuntuでGRUBの起動時間を変更する

grubの起動時間を変更するためのオンライン検索は基本的に/etc/default/grubを変更す...

DOSBox を起動後に自動的にコマンドを実行する方法

DOSBox を使用すると、Windows で DOS をシミュレートし、楽しい作業を行うことができ...

Windows Server 2016 リモート デスクトップ サービスを展開するためのクイック スタート ガイド

現在、2016サーバーは、win2008や2012よりも優れたマルチサイトhttpsサービスをサポー...

テキストエリアタグはサイズ変更できず、マウスでドラッグすることもできません

テキストエリアタグのサイズは不変ですコードをコピーコードは次のとおりです。 <textarea...

MySQL の接続数が多すぎるエラーの原因と解決策

目次概要本日正午、開発およびテスト環境の MySQL サービスで接続数が多すぎるというエラーが報告さ...

Tomcat の設定と Eclipse での起動方法

目次Tomcat8のインストールと設定方法tomcat ダウンロードTomcat マネージャーを有効...

W3C チュートリアル (5): W3C XML アクティビティ

XML は、データを記述、保存、送信、交換するために設計されています。 XML 1.0 は XML ...

CSSでカスタムフォント(font-face)を導入する方法の詳細な説明

なぜこれを使ったのか?それはポスターを作ることから始まりました。それは嵐の夜でした。 。 。さて、無...

Vueは、センシティブな単語フィルタリングコンポーネントを検出するためのさまざまなアイデアを実装しています。

目次前面に書かれた要件分析 v1アイデア1: インターセプションメソッドを使用して入力ボックスの入力...

MySQL で誤って削除したテーブル データを回復する方法 (必読)

バックアップがあれば、非常に簡単です。最新のバックアップ データを生成し、mysqlbinlog を...

Vant Uploaderは1枚以上の写真をアップロードするコンポーネントを実装します

この記事では、1枚以上の写真をアップロードするためのVant Uploaderコンポーネントを紹介し...

Dockerボリュームのファイルマッピング方法

背景ブロックチェーン ログ モジュールで作業しているときに、コンテナーが実行されている場合は、ログ ...