MySQLを活用したあいまい検索の実装手法

1. 業務要件の分析

企業情報管理システムにおいて、重複企業登録を防止するため、新規登録時に類似企業名を検索する必要がある。入力された企業名(略称の場合あり)と既存データベース内の企業名を比較し、類似度の高い順に表示する。

2. 技術的アプローチ

2.1 処理フロー

  1. 企業名から不要情報(地域名、括弧、組織形態等)を除去
  2. IKAnalyzerを使用してキーワード分割
  3. MySQLの正規表現機能で部分一致検索
  4. 一致度に基づいて結果をソート

2.2 実装の選択肢

方法メリットデメリット
LIKE句シンプル部分一致に不向き
全文検索高速カスタマイズ性が低い
正規表現柔軟な検索パフォーマンス中程度

3. 主要な実装コード

3.1 企業名前処理

public String sanitizeCompanyName(String name) {
    // 地域情報の除去
    String regex = "(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)" +
                   "?(?<city>[^市]+自治州|.*?地区|.*?行政単位|.+盟|市辖区|.*?市|.*?県)" +
                   "?(?<county>[^(区|市|県|旗|島)]+区|.*?市|.*?県|.*?旗|.*?島)" +
                   "?(?<village>.*)";
    
    Matcher m = Pattern.compile(regex).matcher(name);
    while(m.find()) {
        name = removeMatchedGroup(name, m.group("province"));
        name = removeMatchedGroup(name, m.group("city")); 
        name = removeMatchedGroup(name, m.group("county"));
    }
    
    // 組織形態の除去
    return name.replaceAll("[(集团|股份|有限|责任|分公司)]", "");
}

private String removeMatchedGroup(String source, String group) {
    return StringUtils.isNotBlank(group) ? source.replace(group, "") : source;
}

3.2 検索クエリ

@Query(value = """
    SELECT * FROM company 
    WHERE isDeleted = '0' 
    AND companyName REGEXP ?1 
    ORDER BY LENGTH(REPLACE(companyName, ?2, ''))/LENGTH(companyName)
    """, nativeQuery = true)
List<Company> findSimilarCompanies(String keywords, String originalName);

3.3 検索ロジック

public List<String> findSimilarCompanies(String inputName) {
    // 前処理
    String sanitized = sanitizeCompanyName(inputName)
                      .replaceAll("[()()]", "");
    
    // 分かち書き
    List<String> tokens = new IKAnalyzer().analyze(sanitized);
    String searchPattern = String.join("|", tokens);
    
    // データベース検索
    return companyRepo.findSimilarCompanies(searchPattern, sanitized)
                     .stream()
                     .map(Company::getName)
                     .collect(Collectors.toList());
}

4. 技術的考慮点

  • IKAnalyzerの辞書を業務ドメインに最適化
  • 検索パフォーマンスのため適切なインデックス設計
  • 大文字小文字、全角半角の統一処理

タグ: MySQL 正規表現 IKAnalyzer あいまい検索 データマッチング

6月30日 20:31 投稿