Elasticsearch (ES) 検索エンジン: テキスト検索: アナライザー/トークナイザー、同義語/ストップ ワード、ピンイン検索、ハイライト表示、スペル修正

元のリンク: https://xiets.blog.csdn.net/article/details/132349032

著作権表示: オリジナル記事の転載は禁止されています

カラムディレクトリ:Elasticsearchカラム(一般ディレクトリ)

テキスト検索は主に全文検索を指します。全文検索は検索エンジンの中核機能です。完全一致の構造化データとは異なり、テキスト (テキスト) データはインデックスの構築や検索時に追加の処理が必要です。

Elasticsearch は、テキスト データの保存と検索時にアナライザー コンポーネントに依存する必要があります。Lucene はインデックスの物理的な構築と並べ替えを担当し、アナライザーはインデックスを確立する前にテキスト データの単語の分割と文法処理を実行します。テキスト データを検索する場合は、最初に検索語をセグメント化して構文化し、次にセグメント化されたサブワードを使用して複数のサブ検索を実行する必要もあります。

全文検索は主にtexttype のフィールドを対象とし、matchクエリ モードを使用して検索します。アナライザーは全文検索の中核です。

1. アナライザー

1.1 フィルタとトークナイザ

アナライザーは、テキスト データを保存または更新するときにインデックスを確立する前にテキストをセグメント化するために使用されます。テキスト タイプのフィールドをクエリする場合は、アナライザーを使用して最初にクエリの単語をセグメント化する必要もあります。

ES にはさまざまな組み込みアナライザーがあり、次の 3 つの部分が含まれます。

  • 文字フィルタ( char_filter): 0 個以上を指定でき、HTML タグの削除、元のテキスト内の特殊文字のエスケープなど、元のテキスト データの大まかな処理を実行します。
  • 単語セグメンター( tokenizer): 指定されたルールに従ってテキストを単語に分割する単語セグメンターは 1 つだけあります。
  • 単語フィルタfilter):0個以上可 単語分割処理結果を受け取り、小文字への変換、同義語の追加、ストップワードの削除、ピンインの追加などの標準化・最適化を行います。

パーサーがテキスト データを処理するとき、テキスト データの 3 つの部分のフロー方向は次のとおりです。

            文本
             |
            \|/
         字符过滤器1
         字符过滤器2
             |
            \|/
           分词器
             |
            \|/
         词语过滤器1
         词语过滤器2
             |
            \|/
    分词1, 分词2, 分词3, ...

1.2 内蔵アナライザー

ES にはさまざまな組み込みアナライザーが付属しています。「組み込みアナライザー リファレンス」を参照してください。

組み込みアナライザーは、追加の構成を行わなくても、任意のインデックスで直接使用できます。組み込みアナライザーの一部を次に示します。

  1. 標準パーサー( standard): Unicode テキスト セグメンテーション アルゴリズムで定義されているように、テキストを単語境界で単語に分割します。ほとんどの句読点や小文字の単語が削除され、ストップ ワードの削除もサポートされます。
  2. 単純なパーサー( simple): 非アルファベット文字 (スペース、句読点など) が見つかると、パーサーはテキストを単語に分割します。単語はすべて小文字です。
  3. ホワイトスペース アナライザー( whitespace): 空白文字が見つかると、アナライザーはテキストを単語に分割します。単語は小文字にされません。
  4. ストップ パーサー( stop):simpleと似ていますが、ストップ ワードの削除をサポートします。
  5. キーワード アナライザー( keyword): 指定されたテキストを受け取り、まったく同じテキストを 1 つの単語として出力する「noop」アナライザー。
  6. Regex Analyzer ( pattern): 正規表現を使用してテキストを単語に分割し、小文字とストップワードをサポートします。
  7. 言語アナライザー( english/ french): 言語固有のアナライザーが多数提供されています。
  8. フィンガープリント アナライザー( fingerprint): 反復検出に使用できるフィンガープリントを作成する専門的なアナライザーです。

アナライザーが指定されていない場合、デフォルトでは、テキスト タイプ フィールドはインデックス作成およびクエリ時に標準アナライザー ( standard) アナライザーを使用します。

標準アナライザー ( ) には、標準standardトークナイザー、小文字トークンフィルター、およびストップ トークン フィルターが含まれます。ストップトークン フィルターはデフォルトで無効になっています。

1.3 テストアナラ​​イザー

アナライザー API: API の分析アナライザーのテスト

ES は、アナライザーの分析結果をテストするための API を提供します。アナライザー関連のリクエスト:

  • GET /_analyze
  • POST /_analyze
  • GET /<index>/_analyze
  • POST /<index>/_analyze

テスト アナライザーのリクエスト形式:

POST /_analyze
{
    
    
    "analyzer": "standard",             // 指定分析器名称
    "text": "ES, Hello World!"          // 需要分析的文本
}

POST /_analyze
{
    
    
    "analyzer": "standard",
    "text": ["test es", "the test"]     // 分析文本也可是传递一个数组, 同时分析多个文本
}

POST /<index>/_analyze                  // 使用索引中自定义的分析器
{
    
    
    "analyzer": "my_analyzer",          // 创建索引时在 settings 中自定义的分析器
    "text": "ES, Hello World!"          // 需要分析的文本
}

POST /<index>/_analyze                  // 基于现有索引的 text 类型字段分析
{
    
    
    "field": "<field_name>",            // 使用给定字段使用的分析器, 如果字段不存在则使用默认分析器
    "text": "ES, Hello World!"          // 需要分析的文本
}

GET /_analyze                           // 也可以自定义分析器 (手动指定分词器和过滤器)
{
    
    
    "char_filter" : ["html_strip"],     // 字符过滤器
    "tokenizer" : "keyword",            // 分词器
    "filter" : ["lowercase"],           // 分词过滤器
    "text" : "this is a <b>test</b>"    // 需要分析的文本
}

テスト アナライザーのリクエスト:

POST /_analyze
{
    
    
    "analyzer": "standard",
    "text": "ES, Hello World!"
}

// 返回
{
    
    
    "tokens": [                     // 每一个分词表示一个 token
        {
    
    
            "token": "es",          // 分词
            "start_offset": 0,      // 分词在原文本中的开始位置
            "end_offset": 2,        // 分词在原文本中的结束位置(不包括)
            "type": "<ALPHANUM>",   // 词类型
            "position": 0           // 该分词是所有分词中的第几个分词
        },
        {
    
    
            "token": "hello",
            "start_offset": 4,
            "end_offset": 9,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
    
    
            "token": "world",
            "start_offset": 10,
            "end_offset": 15,
            "type": "<ALPHANUM>",
            "position": 2
        }
    ]
}

デフォルトのアナライザーを使用して中国語を分析します。

POST /_analyze
{
    
    
    "analyzer": "standard",
    "text": "我是中国人"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "<IDEOGRAPHIC>",
            "position": 0
        },
        {
    
    
            "token": "是",
            "start_offset": 1,
            "end_offset": 2,
            "type": "<IDEOGRAPHIC>",
            "position": 1
        },
        {
    
    
            "token": "中",
            "start_offset": 2,
            "end_offset": 3,
            "type": "<IDEOGRAPHIC>",
            "position": 2
        },
        {
    
    
            "token": "国",
            "start_offset": 3,
            "end_offset": 4,
            "type": "<IDEOGRAPHIC>",
            "position": 3
        },
        {
    
    
            "token": "人",
            "start_offset": 4,
            "end_offset": 5,
            "type": "<IDEOGRAPHIC>",
            "position": 4
        }
    ]
}

標準のアナライザ ( standard) は中国語の単語を処理する際、各漢字を直接単語に分割しますが、一般に中国語の文章には多くの単語が含まれるため、中国語の解析には適していません。

1.4 インデックス作成時にアナライザーを指定する

インデックス マッピングのテキスト タイプ フィールドでは、アナライザを使用する必要があります。アナライザが指定されていない場合は、標準のアナライザ ( ) がデフォルトで使用されますstandard。インデックスの作成時にアナライザを指定することもできます。

インデックスの作成時にデフォルトのアナライザーを指定します。リクエスト形式は次のとおりです。

PUT /<index>                            // 创建索引
{
    
    
    "settings": {
    
                           // 索引设置
        "analysis": {
    
                       // 分析器的所有设置
            "analyzer": {
    
                   // 分析器设置
                "default": {
    
                // 当前索引默认的分析器, text字段如果没有指定分析器则用这个
                    "type": "simple"    // "simple" 表示分析器名称
                }
            }
        }
    },
    "mappings": {
    
                           // 映射
        "properties": {
    
                     // 映射的属性
            // ... 字段列表
        }
    }
}

インデックスを作成するときは、特定のテキスト タイプ フィールドのアナライザーを指定します。リクエストの形式は次のとおりです。

PUT /<index>                                    // 创建索引
{
    
    
    "mappings": {
    
                                   // 映射
        "properties": {
    
                             // 映射的属性
            "<field>": {
    
                            // 字段
                "type": "text",                 // 字段类型
                "analyzer": "standard",         // 当前字段建立索引(写入文档)时使用的分析器
                "search_analyzer": "simple"     // 搜索当前字段时分析搜索词使用的分析器, 如果没有设置则默认与建立索引使用的分析器相同
            }
        }
    }
}

1.5 カスタムアナライザー

アナライザーは文字フィルター、トークナイザー、単語フィルターの組み合わせであり、ES に組み込まれているアナライザーはすでに適切な組み合わせを用意しています。ここでいうカスタムアナライザーとは、ESの既存のフィルターやトークナイザーをベースに組み合わせた新たなアナライザーを指します。

インデックスを作成するときにカスタム アナライザーを使用し、リクエスト形式を指定します。

PUT /<index>
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "tokenizer": {
    
                          // 分词器
                "<tokenizer_name>": {
    
               // 自定义分词器, 节点名称就是自定义的分词器名称
                    "type": "pattern",          // 使用现有分词器, "pattern"表示正则分词器
                    "pattern": "<regex>"        // 用于切分词语的正则表达式, "pattern"分词器的参数
                }
            },
            "char_filter": {
    
                        // 字符过滤器
                "<char_filter_name>": {
    
             // 自定义字符过滤器, 节点名称就是自定义的字符过滤器名称
                    "type": "html_strip"        // 使用现有的字符过滤器, "html_strip"表示用于过滤HTML标签字符的过滤器
                }
            },
            "filter": {
    
                             // 词语过滤器
                "<filter_name>": {
    
                  // 自定义词语过滤器, 节点名称就是自定义的词语过滤器名称
                    "type": "stop",             // 使用现有的词语过滤器, "stop"表示停用词过滤器
                    "ignore_case": true,        // 忽略大小写, "stop"词语过滤器的参数
                    "stopwords": ["the", "is"]  // 停用词, "stop"词语过滤器的参数
                }
            },
            "analyzer": {
    
                                       // 分析器 (分词器 + 字符过滤器 + 词语过滤器)
                "<analyzer_name>": {
    
                            // 自定义分析器, 节点名称就是自定义的分析器名称
                    "tokenizer": "<tokenizer_name>",        // 指定使用的分词器, 必须是现有的或者前面自定义的
                    "char_filter": ["<char_filter_name>"],  // 指定使用的字符过滤器, 必须是现有的或者前面自定义的
                    "filter": ["<filter_name>"]             // 指定使用的词语过滤器, 必须是现有的或者前面自定义的
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "<field>": {
    
    
                "type": "text",
                "analyzer": "<analyzer_name>"   // 指定字段使用的分析器, 必须是现有的或者前面自定义的
            }
        }
    }
}

カスタム アナライザーの例:

PUT /demo-index
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "tokenizer": {
    
    
                "my_tokenizer": {
    
    
                    "type": "pattern",      // 正则分词器
                    "pattern": ","          // 用于切分词语的正则表达式 (用","分隔)
                }
            },
            "char_filter": {
    
    
                "my_char_filter": {
    
    
                    "type": "html_strip"
                }
            },
            "filter": {
    
    
                "my_filter": {
    
    
                    "type": "stop",         // 停用词词语过滤器
                    "ignore_case": true,
                    "stopwords": ["the", "is"]
                }
            },
            "analyzer": {
    
    
                "my_analyzer": {
    
    
                    "tokenizer": "my_tokenizer",
                    "char_filter": ["my_char_filter"],
                    "filter": ["my_filter"]
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
    
                "type": "text",
                "analyzer": "my_analyzer"   // 使用 settings 中自定义的分析器
            }
        }
    }
}

// 测试索引字段中使用的自定义分析器
POST /demo-index/_analyze
{
    
    
    "field": "title",
    "text": "The,Happy,中国人"
}
// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "Happy",
            "start_offset": 4,
            "end_offset": 9,
            "type": "word",
            "position": 1
        },
        {
    
    
            "token": "中国人",
            "start_offset": 10,
            "end_offset": 13,
            "type": "word",
            "position": 2
        }
    ]
}

2.中国語アナライザー

英語に対応して、単語の分割は非常に簡単で、スペースと句読点を使用して単語を分割するだけです。ただし、中国語の単語分割については、ES の組み込みアナライザーでは機能しないため、追加の単語分割プラグインが必要です。ES は、プラグインをインストールすることでサードパーティのアナライザーをサポートできます。より一般的に使用されるサードパーティの中国語アナライザーは、IK と HanLP です。

IK アナライザは、辞書に基づく単語分割アルゴリズムであり、事前に用意された辞書から分析対象のテキストを一定の戦略に従って分析し、テキストが辞書内の特定の単語と一致した場合に単語分割を生成します。辞書ベースの単語分割アルゴリズムは、単語分割アルゴリズムの中で最も単純かつ高速なアルゴリズムであり、順方向最大化マッチング、逆方向最大化マッチング、双方向最大化マッチングの 3 つの異なるマッチング方法に分類できます。

HanLP アナライザーは統計に基づく機械学習アルゴリズムであり、最初にマークされた単語分割形式を含むコーパスを構築する必要があります。次に、テキストを分析するときに、コーパス内の各単語の出現頻度がカウントされ、統計結果に基づいて、特定の文脈で分割されるべき単語の分割が与えられます。

2.1 IKアナライザー

IK アナライザーは、Java 言語に基づいて開発されたオープンソースの軽量の中国語単語セグメンテーション ツールキットです。IK アナライザーは ES プラグイン (IK Analysis for Elasticsearch) を提供し、辞書のコールド アップデートとホット アップデートをサポートします。

IK アナライザー ES プラグイン関連リンク:

2.1.1 IKプラグインのインストール

アナライザープラグインのインストール インストール方法は2通りあります。

インストール方法 1: 手動でダウンロードしてインストールする

  • ; ES バージョンに対応するプラグイン バージョンをプラグイン ダウンロード アドレスからダウンロードしますelasticsearch-analysis-ik-X.X.X.zip
  • ES プラグイン ディレクトリにフォルダーpluginsを作成しますanalysis-ikcd <es-root>/plugins/ && mkdir analysis-ik
  • プラグインを次のplugins/analysis-ikフォルダーに解凍しますunzip elasticsearch-analysis-ik-X.X.X.zip -d <es-root>/plugins/analysis-ik

プラグインの正式名はプラグイン説明ファイル ( plugins/analysis-ik/plugin-descriptor.properties)name=analysis-ikフィールドで定義されていますが、pluginsディレクトリ下のプラグイン フォルダーの名前はカスタマイズできます。

インストール方法2:ESプラグインコマンドを使用してインストールする

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/vX.X.X/elasticsearch-analysis-ik-X.X.X.zip

プラグイン コマンドのオンライン インストールはfile://、次の形式の URL をサポートしています。つまり、プラグインの zip インストール パッケージをローカルにダウンロードしてインストールできます。

plug-inコマンドを使用してプラグインをインストールします。ES設定ファイルディレクトリ( <es-root>/config/)にプラグイン名と同名のフォルダ( )が作成されanalysis-ik、プラグイン設定ファイルがインストールされます。このディレクトリ ( <es-root>/config/analysis-ik) にあります。

インストールされているサードパーティのプラグインを表示するには、リクエストを送信するGET /_cat/plugins?vか、コマンドを実行します./bin/elasticsearch-plugin list

プラグインをインストールした後、ES を再起動する必要があります。コンソールに次の行のログが出力される場合は、IK アナライザー プラグインが正常にインストールされたことを意味します。

[2023-08-09T20:00:00,000][INFO] ... loaded plugin [analysis-ik]

IK プラグインの設定ファイルをロードします。

ES が起動すると、IK プラグインがロードされ、IK ディクショナリ設定がロードされます。ディクショナリ設定ファイルの名前は です。IKAnalyzer.cfg.xml最初にパスからロードされます。ファイルが見つからない場合は、<es-root>/config/analysis-ik/IKAnalyzer.cfg.xmlプラグ内の<es-root>/plugins/analysis-ik/config/IKAnalyzer.cfg.xmlパスからロードされます。-in ディレクトリ。

2.1.2 IK アナライザーの使用

IK プラグインには、同じ名前のik_smart2 つのik_max_wordアナライザー (analyzer) と 2 つのトークナイザー (tokenizer) が含まれています。

ik_smart と ik_max_word の違い:

  • ik_smart はテキストを最も細かい粒度に分割し、可能な組み合わせをすべて網羅します。
  • ik_max_word はテキストを最も粗い粒度に分割します。これはフレーズ クエリに適しています。

IK Analyzer テストを使用してテキストを分析します。

GET /_analyze
{
    
    
    "analyzer": "ik_smart",         // 最粗粒度拆分
    "text": "我是中国人"
}
// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
    
    
            "token": "是",
            "start_offset": 1,
            "end_offset": 2,
            "type": "CN_CHAR",
            "position": 1
        },
        {
    
    
            "token": "中国人",
            "start_offset": 2,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        }
    ]
}

GET /_analyze
{
    
    
    "analyzer": "ik_max_word",      // 最细粒度拆分
    "text": "我是中国人"
}
// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
    
    
            "token": "是",
            "start_offset": 1,
            "end_offset": 2,
            "type": "CN_CHAR",
            "position": 1
        },
        {
    
    
            "token": "中国人",
            "start_offset": 2,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        },
        {
    
    
            "token": "中国",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 3
        },
        {
    
    
            "token": "国人",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 4
        }
    ]
}

2.1.3 IK拡張辞書

IK 単語セグメンタは辞書の単語分割に基づいています。辞書にない単語は分割できません。

GET /_analyze
{
    
    
    "analyzer": "ik_max_word",
    "text": "雄安新区"
}
// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "雄",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
    
    
            "token": "安新",
            "start_offset": 1,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "新区",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 2
        }
    ]
}

「雄安新区」を分割しても「雄安」という単語は分割されませんでした。この単語はデフォルトの辞書に含まれておらず、辞書は手動で拡張できるためです。

IK ディクショナリ設定ファイルは<es-root>/config/analysis-ik/IKAnalyzer.cfg.xmlまたは の<es-root>/plugins/analysis-ik/config/IKAnalyzer.cfg.xml場所にあります。

IKAnalyzer.cfg.xml設定ファイルの内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!-- 用户可以在这里配置自己的扩展字典 -->
    <entry key="ext_dict"></entry>
     <!-- 用户可以在这里配置自己的扩展停止词字典 -->
    <entry key="ext_stopwords"></entry>
    <!-- 用户可以在这里配置远程扩展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!-- 用户可以在这里配置远程扩展停止词字典 -->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

辞書はプレーン テキスト ファイルであり、各行が単語を表します。構成ファイルが配置されているディレクトリにローカルに名前を付けたファイルをIKAnalyzer.cfg.xml作成し、次の内容を書き込みます。my.dic

雄安
雄安新区

構成を変更しますIKAnalyzer.cfg.xml

<!-- 用户可以在这里配置自己的扩展字典 -->
<!-- 配置本地字典文件的路径, 路径必须是相对于配置文件所在目录的相对路径, 多个路径使用 ; 分隔, 文件必须是 UTF-8 编码 -->
<entry key="ext_dict">my.dic</entry>

構成を保存し、ES を再起動します。コンソールに次のログが出力された場合は、拡張辞書が正常にロードされたことを意味します。

[2023-08-09T20:30:00,000][INFO] ... [Dict Loading] .../plugins/analysis-ik/config/my.dic

単語の分割を再度テストします。

GET /_analyze
{
    
    
    "analyzer": "ik_max_word",
    "text": "雄安新区"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "雄安新区",
            "start_offset": 0,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 0
        },
        {
    
    
            "token": "雄安",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "安新",
            "start_offset": 1,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 2
        },
        {
    
    
            "token": "新区",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 3
        }
    ]
}

2.1.4 IKホットアップデート拡張辞書

IK プラグインは辞書のホット アップデートをサポートしています (ES を再起動する必要はありません)。IKAnalyzer.cfg.xml設定ファイルのホット アップデート設定は次のとおりです。

<!-- 用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">words_location</entry>
<!-- 用户可以在这里配置远程扩展停止词字典 -->
<entry key="remote_ext_stopwords">words_location</entry>

ここで、words_locationは 1 つ以上の URL です。たとえばhttp://mysite.com/my.dic、複数の URL を設定でき、複数の URL は;で区切られます。辞書リンクリクエストは以下の2点を満たす必要があります。

  1. この HTTP URL リクエストは、1 行と 1 つの単語で区切られたテキスト コンテンツを返します。
  2. HTTP サーバーはキャッシュ要求をサポートする必要があります (基本的にすべての HTTP サーバーがサポートします)。つまり、応答ヘッダーはLast-Modifiedまたはを返す必要がありますETag

リモート辞書が設定されている場合、IK プラグインは、GET初めてロードされるときに、リモート辞書をロードするリクエストを直接送信します。その後、リクエストは 1 分ごとに送信されHEADIf-Modified-SinceorIf-None-Matchリクエスト ヘッダーが送信されます。HTTP サーバーが 304 Not Modified ステータスを返した場合、処理は行われず、次のリクエストを待ち続けます。 200 OK が返されると、リクエストはすぐに再送信されますGET。更新する辞書コンテンツを取得します。

リモート辞書をロードすると、コンソールに次のログが出力されます。

[2023-08-09T20:35:00.000][INFO] ... [Dict Loading] http://mysite.com/my.dic

注: リモート辞書のホット アップデートでは、アナライザーの辞書のみが更新されます。以前にインデックスが作成されたドキュメント フィールドのインデックスは再作成されませんが、新しく作成されたドキュメントとドキュメントのクエリ時の単語の分割には更新された辞書が使用されます。単語の分割に更新された辞書を使用する必要がある場合は、ドキュメントを再更新し、インデックスを再構築する必要があります。

2.2 HanLP アナライザー

HanLP は、運用環境向けの多言語自然言語処理ツールキットであり、中国語の単語分割、品詞タグ付け、構文分析などの複数の言語処理機能をサポートしています。HanLP には Elasticsearch アナライザー プラグインもあります。

HanLP 関連リンク:

2.2.1 HanLP プラグインのインストール

HanLP ES プラグインをインストールします。

# 需使用兼容 ES 版本的版本
./bin/elasticsearch-plugin install https://github.com/KennFalcon/elasticsearch-analysis-hanlp/releases/download/vX.X.X/elasticsearch-analysis-hanlp-X.X.X.zip

インストールが成功した後、ES を再起動すると、コンソールに次のログが出力されます。

[2023-08-10T20:30:00,000][INFO] ... loaded plugin [analysis-hanlp]

2.2.2 HanLP アナライザーの使用

HanLP ES プラグインによって提供されるアナライザー/トークナイザー:

  • hanlp:HanLP のデフォルトの単語分割
  • hanlp_standard: 標準分詞
  • hanlp_index: 索引分詞
  • hanlp_nlp:NLP 単語分割
  • hanlp_crf:CRF 単語分割
  • hanlp_n_short:N-最短経路分詞
  • hanlp_dijkstra: 最短経路分詞
  • hanlp_speed:極限の辞書単語分割

HanLP パーサーを使用してテキストを分析します。

POST /_analyze
{
    
    
    "analyzer": "hanlp_standard",
    "text": "雄安新区"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "雄",
            "start_offset": 0,
            "end_offset": 1,
            "type": "ag",
            "position": 0
        },
        {
    
    
            "token": "安",
            "start_offset": 1,
            "end_offset": 2,
            "type": "ag",
            "position": 1
        },
        {
    
    
            "token": "新区",
            "start_offset": 2,
            "end_offset": 4,
            "type": "n",
            "position": 2
        }
    ]
}

単語分割の結果は「雄安」を分割しなかったため、拡張辞書に追加する必要があります。

2.2.3 HanLP拡張辞書

ディレクトリにファイル<es_root>/plugins/analysis-hanlp/data/dictionary/custom/を作成しmydict.txt、次の内容を入力します。

雄安

辞書テキストの各行は分詞です。

HanLP プラグインの設定ファイルの場所:<es_root>/config/analysis-hanlp/hanlp.propertiesまたは<es_root>/plugins/analysis-hanlp/config/hanlp.properties

hanlp.properties構成ファイル内のフィールドの値を変更しCustomDictionaryPath、拡張辞書ファイルのパスを末尾に追加します。

# 路径默认相对于 analysis-hanlp 插件根目录, 多个路径使用 ; 分隔
CustomDictionaryPath=...;data/dictionary/custom/mydict.txt;

ES を再起動し、アナライザーを再度テストします。

POST /_analyze
{
    
    
    "analyzer": "hanlp_standard",
    "text": "雄安新区"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "雄安",
            "start_offset": 0,
            "end_offset": 2,
            "type": "n",
            "position": 0
        },
        {
    
    
            "token": "新区",
            "start_offset": 2,
            "end_offset": 4,
            "type": "n",
            "position": 1
        }
    ]
}

2.2.4 HanLPホットアップデート拡張辞書

HanLP プラグイン構成のホット アップデート辞書構成ファイルの場所:<es_root>/config/analysis-hanlp/hanlp-remote.xmlまたは<es_root>/plugins/analysis-hanlp/config/hanlp-remote.xml

hanlp-remote.xml設定ファイルの内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>HanLP Analyzer 扩展配置</comment>
    <!-- 用户可以在这里配置远程扩展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry>-->
    <!-- 用户可以在这里配置远程扩展停止词字典 -->
    <!-- <entry key="remote_ext_stopwords">stop_words_location</entry> -->
</properties>

ここで、 はまたはwords_locationです。たとえば、次のようになります。URLURL 词性

  • http://mysite.com/mydic.txt
  • http://mysite.com/mydic.txt nt

詳細については、「HanLP リモート辞書の設定」を参照してください。

NanLP リモート拡張辞書のロード ルールは、IK リモート拡張辞書のロード ルールと同じで、1 分ごとに URL を要求して更新があるかどうかを確認し、更新があればリモート辞書をリロードします。

3. 同義語を使用する

検索エンジンでは、同じターゲットを検索するさまざまなクエリ用語を処理するために同義語が使用されます。たとえば、ユーザーが「Android フォン」と「Android フォン」を検索するとき、実際には同じターゲットを検索したいと考えています。たとえば、電子商取引の検索では、ユーザーは「パイナップル」と「パイナップル」、「トマト」と「トマト」、「炊飯器」と「炊飯器」、「Li-Ning」と「LI-NING」を検索します。同じ商品です。

ES では、アナライザーの単語分割フィルターによる同義語検索が実装されています。同義語を使用するには、インデックスの構築時に同義語のインデックスを同時に作成するか、検索中に同義語アナライザーを通じて同義語を同時に検索できます。

ES の組み込みの単語セグメンテーション フィルターsynonymsynonym_graph同義語フィルターをサポートします。

3.1 インデックスの作成時に同義語を使用する

インデックスを構築するときに同義語を使用するために、ES には組み込みのsynonym同義語セグメンテーション フィルターがあります。以下では、IK アナライザーと同義語単語セグメンテーション フィルターを使用してインデックスを作成します。

PUT /menu
{
    
    
    "settings": {
    
                                   // 索引设置
        "analysis": {
    
    
            "filter": {
    
                             // 过滤器定义
                "my_filter": {
    
                      // 自定义分词过滤器, 名称为 "my_filter"
                    "type": "synonym",          // 使用内置的 同义词过滤器
                    "synonyms": [               // 同义词列表, 同义词之间用 , 分隔
                        "凤梨,菠萝",
                        "番茄,西红柿"
                    ]
                }
            },
            "analyzer": {
    
                           // 分析器定义
                "my_analyzer": {
    
                    // 自定义分析器, 名称为 "my_analyzer"
                    "tokenizer": "ik_max_word", // 分词器, 使用安装的第三方分词器 "ik_max_word"
                    "filter": [                 // 分词过滤器
                        "lowercase",            // 自带的分词过滤器
                        "my_filter"             // 前面自定义的分词过滤器
                    ]
                }
            }
        }
    },
    "mappings": {
    
                                   // 映射
        "properties": {
    
    
            "name": {
    
                               // text类型的字段
                "type": "text",
                "analyzer": "my_analyzer"       // 使用上面自定义的分析器
            }
        }
    }
}

インデックス内のカスタム アナライザーをテストします。

GET /menu/_analyze
{
    
    
    "field": "name",
    "text": "西红柿炒蛋"
}

// 返回, 西红柿除了拆分出“西红柿”外, 还拆分出了它的同义词“番茄”
{
    
    
    "tokens": [
        {
    
    
            "token": "西红柿",
            "start_offset": 0,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 0
        },
        {
    
    
            "token": "番茄",
            "start_offset": 0,
            "end_offset": 3,
            "type": "SYNONYM",
            "position": 0
        },
        {
    
    
            "token": "炒蛋",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 1
        }
    ]
}

いくつかのドキュメントを作成します。

PUT /menu/_doc/001
{
    
    "name": "番茄炒蛋"}

PUT /menu/_doc/002
{
    
    "name": "凤梨炒西红柿"}

PUT /menu/_doc/003
{
    
    "name": "菠萝猪扒包"}

ドキュメントの検索:

GET /menu/_search
{
    
    
    "query": {
    
    
        "match": {
    
    
          "name": "番茄"
        }
    }
}

// 返回
{
    
    
    "took": 436,
    "timed_out": false,
    "_shards": {
    
    
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.7520058,
        "hits": [
            {
    
    
                "_index": "menu",
                "_id": "001",
                "_score": 0.7520058,
                "_source": {
    
    
                    "name": "番茄炒蛋"
                }
            },
            {
    
    
                "_index": "menu",
                "_id": "002",
                "_score": 0.6951314,
                "_source": {
    
    
                    "name": "凤梨炒西红柿"
                }
            }
        ]
    }
}

返された結果から、「トマト」を検索すると、「トマト スクランブルエッグ」に加えて、「パイナップル フライド トマト」にも一致したことがわかります。

3.2 検索時に同義語を使用する

同義語を検索するという目的は、ドキュメントのインデックス作成時または検索時に達成できるため、両方の場所で同義語を使用する必要はありません。ドキュメントのインデックス作成時に同義語を使用せず、検索時に同義語検索を使用すると、ドキュメントのインデックスの数を減らすことができ、後で同義語を更新するときにドキュメントのインデックスを再作成する必要がなくなります。

検索時に同義語フィルターを使用したインデックスの作成:

PUT /menu
{
    
    
    "settings": {
    
                                   // 索引设置
        "analysis": {
    
    
            "filter": {
    
                             // 过滤器定义
                "my_filter": {
    
                      // 自定义分词过滤器, 名称为 "my_filter"
                    "type": "synonym",          // 使用内置的 同义词过滤器
                    "synonyms": [               // 同义词列表, 同义词之间用 , 分隔
                        "凤梨,菠萝",
                        "番茄,西红柿"
                    ]
                }
            },
            "analyzer": {
    
                           // 分析器定义
                "my_analyzer": {
    
                    // 自定义分析器, 名称为 "my_analyzer"
                    "tokenizer": "ik_max_word", // 分词器, 使用安装的第三方分词器 "ik_max_word"
                    "filter": [                 // 分词过滤器
                        "lowercase",            // 自带的分词过滤器
                        "my_filter"             // 前面自定义的分词过滤器
                    ]
                }
            }
        }
    },
    "mappings": {
    
                                   // 映射
        "properties": {
    
    
            "name": {
    
                               // text类型的字段
                "type": "text",
                "analyzer": "ik_max_word",          // 文档建立索引时使用 "ik_max_word" 分析器
                "search_analyzer": "my_analyzer"    // 搜索时使用上面自定义的分析器
            }
        }
    }
}

3.3 同義語辞書の使用

同義語が多数ある場合、settings設定は非常に煩雑になり、同義語辞書を更新するのは簡単ではありません。ES の組み込みシノニム フィルタは、ローカル テキスト ファイルへのシノニムの配置をサポートしています。ファイルの場所はディレクトリ内にあり<es_root>/config/、各クラスタ ノードに配置されている必要があります。

以下に示すように、<es_root>/config/ディレクトリにフォルダーを作成しmydictそのフォルダーにsynonyms.txtテキスト ファイルをダウンロードして作成して、同義語を 1 行に 1 つの同義語グループとして保存し、同義語間を区切ります。,

<es_root>$ cat config/mydict/synonyms.txt
凤梨,菠萝
番茄,西红柿

ES の組み込み同義語フィルターを使用して、インデックスの作成時にsynonym_graphアナライザーをカスタマイズし、同義語にはローカル辞書を使用します。

PUT /menu
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "filter": {
    
    
                "my_filter": {
    
                                  // 自定义分词过滤器
                    "type": "synonym_graph",                // 使用内置的 同义词过滤器
                    "synonyms_path": "mydict/synonyms.txt"  // 指定同义词词典, 文件路径相对于 `<es_root>/config/` 目录
                }
            },
            "analyzer": {
    
    
                "my_analyzer": {
    
                    // 自定义分析器
                    "tokenizer": "ik_max_word",
                    "filter": [                 // 分词过滤器
                        "lowercase",
                        "my_filter"             // 前面自定义的分词过滤器
                    ]
                }
            }
        }
    },
    "mappings": {
    
                                       // 映射
        "properties": {
    
    
            "name": {
    
                                   // text类型的字段
                "type": "text",
                "analyzer": "ik_max_word",
                "search_analyzer": "my_analyzer"    // 使用上面自定义的分析器
            }
        }
    }
}

4. ストップワードを使用する

ストップワード(Stop Word)とは、テキスト分割後の単語のうち、検索意味を持たない一部の単語を指します。たとえば、「ここの景色が好きです」というテキストがありますが、単語分割後の単語
「I」、「here」、「the」は非常に頻繁に使用されており、テキスト情報を取得する上で固有の意味を持ちません。これらのストップ ワードは無視できるため、インデックス作成と検索の効率が向上し、ストレージ スペースが節約されます。

次の Web サイトには、英語と中国語で一般的に使用されるストップワードのリストがあります。

文字フィルタを使用したフィルタリングに加えて、HTML タグなどの特殊文字もストップワード フィルタを使用してフィルタリングできます。

4.1 ストップワードフィルター

ES の組み込みのstop単語セグメンテーション フィルターを使用して、ストップ ワードをフィルター処理できます。

インデックスを作成し、単語分割フィルターをカスタマイズし、ストップ ワードを使用します。

PUT /demo
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "filter": {
    
    
                "my_stop_filter": {
    
             // 自定义分词过滤器
                    "type": "stop",                     // 使用内置的停用词过滤器
                    "stopwords": ["我", "这里", "的"]    // 停用词列表
                }
            },
            "analyzer": {
    
    
                "my_analyzer": {
    
                // 自定义分析器
                    "tokenizer": "ik_max_word",
                    "filter": ["my_stop_filter"]
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
    
                "type": "text",
                "analyzer": "my_analyzer"   // 使用自定义的分析器
            }
        }
    }
}

インデックス マップされたフィールドのアナライザーをテストします。

POST /demo/_analyze
{
    
    
    "field": "title",
    "text": "我喜欢这里的风景"
}

// 返回, 从返回中可以看出, “我”、“这里”、“的” 被过滤掉了
{
    
    
    "tokens": [
        {
    
    
            "token": "喜欢",
            "start_offset": 1,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "风景",
            "start_offset": 6,
            "end_offset": 8,
            "type": "CN_WORD",
            "position": 4
        }
    ]
}

フィルターなしでアナライザーをテストしますstop

POST /_analyze
{
    
    
    "analyzer": "ik_max_word",
    "text": "我喜欢这里的风景"
}

// 返回, 没有使用停止词过滤器 “我”、“这里”、“的” 没有被过滤掉
{
    
    
    "tokens": [
        {
    
    
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
    
    
            "token": "喜欢",
            "start_offset": 1,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "这里",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        },
        {
    
    
            "token": "的",
            "start_offset": 5,
            "end_offset": 6,
            "type": "CN_CHAR",
            "position": 3
        },
        {
    
    
            "token": "风景",
            "start_offset": 6,
            "end_offset": 8,
            "type": "CN_WORD",
            "position": 4
        }
    ]
}

4.2 内蔵アナライザーはストップワードを使用します

多くの組み込みアナライザーにはストップ ワード フィルターが付属しており、関連するパラメーターが設定されている限り使用できます。

以下では、組み込みアナライザーを使用し、ストップワード パラメーターstandardを設定してstopwordsアナライザーをカスタマイズし、インデックスを作成します。

PUT /demo
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "analyzer": {
    
    
                "my_standard": {
    
    
                    "type": "standard",
                    "stopwords": ["the", "a"]
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
    
                "type": "text",
                "analyzer": "my_standard"
            }
        }
    }
}

インデックス付きフィールドのアナライザーをテストします。

POST /demo/_analyze
{
    
    
    "field": "title",
    "text": "the a beautiful view."
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "beautiful",
            "start_offset": 6,
            "end_offset": 15,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
    
    
            "token": "view",
            "start_offset": 16,
            "end_offset": 20,
            "type": "<ALPHANUM>",
            "position": 3
        }
    ]
}

4.3 IK アナライザーはストップワードを使用します

IK アナライザーはデフォルトで英語のストップ ワードのみを使用し、中国語のストップ ワードは使用しません。拡張ストップワード辞書およびリモート拡張ストップワード辞書は、 IK プラグインのIKAnalyzer.cfg.xml辞書設定ファイルで設定できます。

IKAnalyzer.cfg.xml設定ファイル:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!-- 用户可以在这里配置自己的扩展字典 -->
    <entry key="ext_dict"></entry>
     <!-- 用户可以在这里配置自己的扩展停止词字典 -->
    <entry key="ext_stopwords"></entry>
    <!-- 用户可以在这里配置远程扩展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!-- 用户可以在这里配置远程扩展停止词字典 -->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

ストップワード辞書の設定は、拡張辞書の設定と同じです。IK辞書設定ファイルが配置されているディレクトリにファイルIKAnalyzer.cfg.xmlを作成し、内容を書き込みます。my_stopwords.dic

$ cat my_stopwords.dic
我
这里
的

IK 辞書構成ファイルを変更し、ローカル拡張ストップワードを構成します。

<entry key="remote_ext_dict">my_stopwords.dic</entry>

設定を保存して ES を再起動すると、コンソールにはストップ ワード辞書が正常にロードされたことを示す次のログが出力されます。

[2023-08-10T20:30:00,000][INFO] ... [Dict Loading] .../plugins/analysis-ik/config/my_stopwords.dic

ストップワードを設定した IK アナライザーを使用してテキストを分析します。

POST /_analyze
{
    
    
    "analyzer": "ik_max_word",
    "text": "我喜欢这里的风景"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "喜欢",
            "start_offset": 1,
            "end_offset": 3,
            "type": "CN_WORD",
            "position": 0
        },
        {
    
    
            "token": "风景",
            "start_offset": 6,
            "end_offset": 8,
            "type": "CN_WORD",
            "position": 1
        }
    ]
}

IK アナライザーはリモート拡張ストップワード辞書の設定 (ストップワード ホット アップデート) をサポートしており、設定方法はリモート拡張辞書の設定と同じです。

4.4 HanLP パーサーはストップワードを使用します

HanLP プラグインのパーサーは、デフォルトではストップワードを有効にしません。

POST /_analyze
{
    
    
    "analyzer": "hanlp_standard",
    "text": "我喜欢这里的风景"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "rr",
            "position": 0
        },
        {
    
    
            "token": "喜欢",
            "start_offset": 1,
            "end_offset": 3,
            "type": "vi",
            "position": 1
        },
        {
    
    
            "token": "这里",
            "start_offset": 3,
            "end_offset": 5,
            "type": "rzs",
            "position": 2
        },
        {
    
    
            "token": "的",
            "start_offset": 5,
            "end_offset": 6,
            "type": "ude1",
            "position": 3
        },
        {
    
    
            "token": "风景",
            "start_offset": 6,
            "end_offset": 8,
            "type": "n",
            "position": 4
        }
    ]
}

HanLP アナライザーのストップ ワードを有効にします。これはカスタム アナライザーで有効にできます。

PUT /demo
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "analyzer": {
    
    
                "my_hanlp": {
    
                               // 自定义分析器
                    "type": "hanlp_standard",           // 使用 HanLP 插件中的分析器
                    "enable_stop_dictionary": true      // 启用停用词词典
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
    
                "type": "text",
                "analyzer": "my_hanlp"      // 使用自定义分析器
            }
        }
    }
}

インデックス付きフィールドのアナライザーをテストします。

POST /demo/_analyze
{
    
    
    "field": "title",
    "text": "我喜欢这里的风景"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "喜欢",
            "start_offset": 1,
            "end_offset": 3,
            "type": "vi",
            "position": 0
        },
        {
    
    
            "token": "风景",
            "start_offset": 6,
            "end_offset": 8,
            "type": "n",
            "position": 1
        }
    ]
}

HanLP アナライザーのストップ ワード ディクショナリは、ローカル拡張とリモート拡張をサポートしています。ローカル拡張は、プラグイン構成ファイルのフィールド値で構成されます。フィールドのデフォルト値は です。拡張ストップ ワードを直接拡張ストップ ワードに追加することもでき<es_root>/config/analysis-hanlp/hanlp.propertiesます。ファイルの終わり。CoreStopWordDictionaryPath<es_root>/plugins/analysis-hanlp/data/dictionary/stopwords.txt

HanLP アナライザーのリモート ストップワード辞書は、拡張リモート辞書と同じ方法で構成され、<es_root>/config/analysis-hanlp/hanlp-remote.xml構成ファイルで構成されます。

5.ピンイン検索

ピンイン検索は中国語の検索で非常に実用的です。中国語では通常、ピンイン入力方式が使用されます。ピンイン検索がサポートされている場合、ユーザーはピンインまたはキーワードの最初の文字を入力するだけで、関連する結果を検索できます。

ピンイン検索をサポートするには、ES ピンイン アナライザー プラグインをインストールする必要があります: https://github.com/medcl/elasticsearch-analysis-pinyin

5.1 ピンインプラグインのインストール

Analysis-pinyin プラグインはコンパイルおよびパッケージ化されていないため、自分でプロジェクトをビルドする必要があります。ES Pinyin プラグイン プロジェクトをコンパイルするには、Git および Maven ツールがローカルにインストールされていることを確認する必要があります。

まず、Git リポジトリをローカルにクローンします。

git clone https://github.com/medcl/elasticsearch-analysis-pinyin.git

pom.xmlプロジェクト内のファイルのフィールドの値をelasticsearch.versionES と同じバージョン番号に変更します。

<project>
    <properties>
        <elasticsearch.version>8.8.2</elasticsearch.version>
    </properties>
</project>

Maven を使用してプロジェクトをビルドし、プロジェクトのルート ディレクトリ (ファイルが存在するディレクトリ)pom.xmlでコマンドを実行します。

mvn install

コンパイル プロセス中に、依存関係パッケージとプラグインが最初にダウンロードされます。しばらくお待ちください。ビルドが成功すると、圧縮<project_root>/target/releasesパッケージがディレクトリに生成されますelasticsearch-analysis-pinyin-X.X.X.zip。これがコンパイルおよびパッケージ化された ES プラグインです。

ES プラグインをインストールするには、プラグインの圧縮パッケージを<es_root>/plugins/ディレクトリに直接抽出するか、プラグイン コマンドを使用してインストールします。

$ ./bin/elasticsearch-plugin install file:///.../target/releaseselasticsearch-analysis-pinyin-X.X.X.zip

インストールされているプラ​​グインを表示します。

$ ./bin/elasticsearch-plugin list
analysis-hanlp
analysis-ik
analysis-pinyin

ES を再起動すると、プラグインが正常にロードされたことを示す次のログがコンソールに出力されます。

[2023-08-10T20:30:00,000][INFO] ... loaded plugin [analysis-hanlp]
[2023-08-10T20:30:00,000][INFO] ... loaded plugin [analysis-ik]
[2023-08-10T20:30:00,000][INFO] ... loaded plugin [analysis-pinyin]

5.2 ピンインプラグインの使用

分析ピンイン プラグインには次のものが含まれます。

  • アナライザ:pinyin
  • トークナイザー:pinyin
  • 単語分割フィルター:pinyin

ピンイン アナライザーをテストします。

POST /_analyze
{
    
    
    "analyzer": "pinyin",
    "text": "美丽的风景"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "mei",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 0
        },
        {
    
    
            "token": "mldfj",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 0
        },
        {
    
    
            "token": "li",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 1
        },
        {
    
    
            "token": "de",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 2
        },
        {
    
    
            "token": "feng",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 3
        },
        {
    
    
            "token": "jing",
            "start_offset": 0,
            "end_offset": 0,
            "type": "word",
            "position": 4
        }
    ]
}

ピンイン アナライザの単語分割は比較的単純です。デフォルトでは、ピンイン単語分割と、キーワード内の各漢字の最初の文字で構成される単語分割のみが分離されます。オプションのパラメータも多数あります。「入門」を参照してください。 GitHubウェアハウス

以下では、IK 単語セグメンターとピンイン単語セグメンテーション フィルターを使用してカスタム アナライザーを形成します。

PUT /demo
{
    
    
    "settings": {
    
    
        "analysis": {
    
    
            "filter": {
    
    
                "my_pinyin": {
    
                          // 自定义分词过滤器
                    "type": "pinyin",               // 使用 "pinyin" 分词过滤器
                    "keep_first_letter": true,      // 保留首字母
                    "keep_full_pinyin": true,       // 保留全拼
                    "keep_original": true,          // 保留原始输入
                    "lowercase": true               // 小写
                }
            },
            "analyzer": {
    
    
                "my_ik_pinyin": {
    
                       // 自定义分析器
                    "tokenizer": "ik_max_word",     // 使用 "ik_max_word" 分词器
                    "filter": ["my_pinyin"]         // 使用自定义的分析器
                }
            }
        }
    },
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
                                  // text 类型的索引字段
                "type": "text",
                "analyzer": "my_ik_pinyin"          // 使用自定义的分析器
            }
        }
    }
}

インデックス内のカスタム アナライザーをテストします。

POST /demo/_analyze
{
    
    
    "analyzer": "my_ik_pinyin",
    "text": "美丽的风景"
}

// 返回
{
    
    
    "tokens": [
        {
    
    
            "token": "mei",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
    
    
            "token": "li",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "美丽",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "ml",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 1
        },
        {
    
    
            "token": "feng",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        },
        {
    
    
            "token": "jing",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 3
        },
        {
    
    
            "token": "风景",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 3
        },
        {
    
    
            "token": "fj",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 3
        }
    ]
}

いくつかのドキュメントを作成します。

PUT /demo/_doc/001
{
    
    "title": "美丽的风景"}

PUT /demo/_doc/002
{
    
    "title": "附近的景区"}

ピンイン検索:

POST /demo/_search
{
    
    
    "query": {
    
    
        "match": {
    
    
            "title": "fujin"
        }
    }
}

// 返回
{
    
    
    "took": 1,
    "timed_out": false,
    "_shards": {
    
    
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.7427702,
        "hits": [
            {
    
    
                "_index": "demo",
                "_id": "002",
                "_score": 1.7427702,
                "_source": {
    
    
                    "title": "附近的景区"
                }
            }
        ]
    }
}

ピンインの最初の文字の検索:

POST /demo/_search
{
    
    
    "query": {
    
    
        "match": {
    
    
            "title": "fj"
        }
    }
}

// 返回
{
    
    
    "took": 1,
    "timed_out": false,
    "_shards": {
    
    
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.22920428,
        "hits": [
            {
    
    
                "_index": "demo",
                "_id": "001",
                "_score": 0.22920428,
                "_source": {
    
    
                    "title": "美丽的风景"
                }
            },
            {
    
    
                "_index": "demo",
                "_id": "002",
                "_score": 0.22920428,
                "_source": {
    
    
                    "title": "附近的景区"
                }
            }
        ]
    }
}

6. ハイライト

文字検索の際、キーワードに一致した部分を強調表示する、つまり一致したキーワードに色やフォントの加工を施す必要がある場合があります。

ハイライト公式サイト紹介:ハイライト

まずインデックスを作成し、テキストを書き込みます。

PUT /demo
{
    
    
    "mappings": {
    
    
        "properties": {
    
    
            "title": {
    
    
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
    }
}

PUT /demo/_doc/001
{
    
    "title": "美丽的风景"}

PUT /demo/_doc/002
{
    
    "title": "附近的风景"}

6.1 検索結果のハイライト表示

強調表示は、返された結果内の一致するキーワードにタグを追加することによって実現されます。検索によって返された強調表示された結果の例:

POST /demo/_search          // 搜索
{
    
    
    "query": {
    
    
        "match": {
    
              // 分词查询
          "title": "风景"
        }
    },
    "highlight": {
    
              // 高亮设置
        "fields": {
    
             // 需要高亮的字段
            "title": {
    
          // 高亮 "title" 字段匹配部分
                "pre_tags": "<font color='red'>",       // 高亮词的前标签, 默认为 "<em>"
                "post_tags": "</font>"                  // 高亮词的后标签, 默认为 "</em>"
            }
        }
    }
}

// 返回
{
    
    
    "took": 2,
    "timed_out": false,
    "_shards": {
    
    
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.18232156,
        "hits": [
            {
    
    
                "_index": "demo",
                "_id": "001",
                "_score": 0.18232156,
                "_source": {
    
    
                    "title": "美丽的风景"
                },
                "highlight": {
    
    
                    "title": [
                        "美丽的<font color='red'>风景</font>"
                    ]
                }
            },
            {
    
    
                "_index": "demo",
                "_id": "002",
                "_score": 0.18232156,
                "_source": {
    
    
                    "title": "附近的风景"
                },
                "highlight": {
    
    
                    "title": [
                        "附近的<font color='red'>风景</font>"
                    ]
                }
            }
        ]
    }
}

6.2 ハイライト戦略

unifiedES は、と の 3 つの強調表示方法をサポートしています。plainこれらfvhは、 を検索するときにパラメータを指定することによって指定されますhighlight.fields.<field>.type

unifiedこれは ES のデフォルトの強調表示戦略であり、Lucene Unified Highlighter を使用して実装され、BM25 アルゴリズムを使用して個々の文をコーパス内の文書であるかのようにスコア付けします。

plainこの戦略では、標準の Lucene ハイライターを使用します。この戦略はより正確です。すべてのドキュメントをメモリにロードし、クエリと分析を再実行する必要があります。この戦略は、多数のドキュメントのテキストの強調表示を処理するときに多くのリソースを必要とするため、単一フィールドのドキュメントの検索強調表示により適しています。

fvh(高速ベクター ハイライター) 戦略では、Lucene 高速ベクター ハイライターを使用します。これは、ドキュメントに大きなテキスト フィールドが含まれる場合の使用に適しています。

検索時の強調表示戦略を指定します。

POST /demo/_search
{
    
    
    "query": {
    
    
        "match": {
    
    
          "title": "风景"
        }
    },
    "highlight": {
    
    
        "fields": {
    
    
            "title": {
    
    
                "pre_tags": "<font color='red'>",
                "post_tags": "</font>",
                "type": "plain"         // 指定高亮策略
            }
        }
    }
}

7. スペル修正

ユーザーが検索キーワードを入力する際、発音やストロークが似ているタイプミスを入力することがありますが、タイプミスを含むキーワードを検索する場合、多くの検索エンジンは自動的に識別し、修正後の正しいキーワードを自動的に検索します。

7.1 スペル修正の実装原則

ES が全文検索 (matchクエリ) を実行する場合、編集距離パラメーター ( fuzziness) を指定できます。編集距離とは、単語を編集して別の単語を取得できる回数を指します。編集操作には、文字の置換、文字の削除、文字の挿入、2 つの文字の位置の交換が含まれます。各操作が編集距離となります。たとえば、「Nan Da Dao」から「Shen Nan Da Dao」まで、「Nan」を「南」に置き換え、頭に「深」を挿入すると、「Shen Nan Da Dao」になります。 「Nan Da Dao」 「Shennan Avenue」までの編集距離は 2 です。

スペル ミスを修正するには、まず人気の検索ワードを保存するためのインデックスを作成します。ユーザーが指定したキーワードを使用してコンテンツを検索できない場合は、そのキーワードを使用して人気の検索ワード インデックスを検索し、編集距離を指定します(正しい検索ワード)、正しいホット検索ワードを使用してコンテンツを検索します。

7.2 ホット検索語を使用して検索語を修正する

人気の検索用語のインデックスを作成し、いくつかのドキュメントを作成します。

PUT /hotword
{
    
    
    "mappings": {
    
    
        "properties": {
    
    
            "hotword": {
    
                        // text类型的字段
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
    }
}

PUT /hotword/_doc/001
{
    
    "hotword": "环城大道"}

PUT /hotword/_doc/002
{
    
    "hotword": "林荫小道"}

PUT /hotword/_doc/003
{
    
    "hotword": "滨海立交"}

編集距離を 1 に指定し、キーワードを検索します。

POST /hotword/_search
{
    
    
    "query": {
    
    
        "match": {
    
    
            "hotword": {
    
    
                "query": "幻城大道",      // 搜索词, 将分词为 "幻城" 和 "大道"
                "fuzziness": 1          // 最大编辑距离为 1
            }
        }
    }
}

// 返回
{
    
    
    "took": 2,
    "timed_out": false,
    "_shards": {
    
    
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.9808291,
        "hits": [
            {
    
    
                "_index": "hotword",
                "_id": "001",
                "_score": 0.9808291,
                "_source": {
    
    
                    "hotword": "环城大道"       // "大道" 匹配 "环城大道"
                }
            },
            {
    
    
                "_index": "hotword",
                "_id": "002",
                "_score": 0.49041456,
                "_source": {
    
    
                    "hotword": "林荫小道"       // "大道" 经过1个编辑距离后得到 "小道", 匹配 "林荫小道"
                }
            }
        ]
    }
}

「Huancheng Avenue」の単語分割検索では、2 つの分詞「Huancheng」と「Avenue」が分離されます。そのうち、「Avenue」は「Ringcheng Avenue」と一致し、「Avenue」は 1 編集距離を通過して「Xiaodao」を取得し、その後「Xiaodao」を取得します。 「Xiaodao」 と 「Boulevard Avenue」 が一致するため、検索結果には「Ring City Avenue」 と 「Boulevard Road」 が含まれます。編集された単語分割一致スコアは元の単語分割一致スコアよりも低いため、「Boulevard Avenue」の一致スコアは「Ring City Avenue」の一致スコアよりもはるかに低くなります。

ユーザーが「Huancheng Avenue」を使用してドキュメントを検索するときに、返された結果が空であるか、データ量が非常に少ない場合は、「Huancheng Avenue」を使用してホット検索ワード インデックスから検索を試みることができ、結果は次のようになります。スコアが最も高いキーワード「Huancheng Avenue」を検索し、次にキーワード「Ringcheng Avenue」を使用して元の文書を検索することで、ある程度のスペル修正が行われます。

スペル修正に関する別の考え方: ほとんどのユーザーが使用する入力方法は基本的にピンイン入力であるため、ユーザーが入力した間違ったキーワードは正しいピンインである可能性が高くなります。ピンイン解析機能を利用して、注目ワードインデックスのキーワードフィールドを分割し、間違ったキーワードで検索ワードインデックスを検索する場合、ピンインに変換して検索します。ピンインを使用して、ホット検索ワードから正しいキーワードを検索します。検索ワードインデックス。

おすすめ

転載: blog.csdn.net/xietansheng/article/details/132349032