Upgrade to Pro — share decks privately, control downloads, hide ads and more …

グラフデータベースでも全文検索がんばりたい

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 グラフデータベースでも全文検索がんばりたい

■ イベント
Search Engineering Tech Talk 2026 Summer
https://search-tech.connpass.com/event/396099/

■登壇概要
タイトル:グラフデータベースでも全文検索がんばりたい
登壇者:Sansan株式会社 南 直人

■ 技術本部 採用情報
https://media.sansan-engineering.com

Avatar for SansanTech

SansanTech PRO

July 23, 2026

More Decks by SansanTech

Other Decks in Technology

Transcript

  1. 南 直人 Sansan株式会社 技術本部 Contract One Engineering Unit Senior Software

    Engineer – Search, AI 写真が入ります 2019/04 – 2026/02: Solr向けランキングプラグイン 開発 2026/03 – 現在: 契約書領域 AI・検索エンジニア 全文検索エンジンやベクトル検索エンジン 最近 知識グラフについて勉強中 今日 知識グラフで 検索 話をします アルゴリズムが好き
  2. 知識グラフと ? エンティティとエンティティをリレーションでつないだデータ構造 エンティティ:人、も 、概念など 個別 情報 リレーション:エンティティ同士 関係性 契約領域

    場合 例 条項 参 照 す る 含む 参照する 契約する 企業 定義する 契約 定義語 含む る す 照 契 参 る す 約 条項 個人 契約 3
  3. 知識グラフにおける検索と ? 構造的な検索 検索起点となるアンカーノードから グラフトラバーサルによる検索。例え 、2つ エンティティ間に パスが存在するか。 語彙的な検索 ←

    今回 エンティティ ココ 名前やメタデータに対する語彙的な検索。アンカーノード 決定 ため 検索。 意味的な検索 意味一致による検索。エンティティを埋め込む手法やグラフ構造を埋め込む手法が存在する。 エンティティ埋め込み:アンカーノード 決定やスコアリング グラフ 構造埋め込み:スコアリングがメイン 4
  4. グラフデータベースで 日本語検索 グラフデータベース グラフ構造 Neo4jで データを保存・検索するため 日本語 データベース。今回 Neo4jを使用。 語彙検索

    バックエンドにLuceneが使われている。ただし、日本語 形態素解析器(Kuromoji) 用できない(CJK Analyzer 検索エンジニアとして Neo4jに Lucene デフォルトで使 デフォルト組み込み)注1 CJK AnalyzerよりもKuromojiを使いたい Analyzer を返却することを責務とする AnalyzerProvider というインターフェー スが存在し、Analyzer をカスタムすることができる。 注1:Elasticsearchなど全文検索エンジンを使用してアンカーノード 決定部分を外部に切り出す方法も考えられる 5
  5. Neo4jで AnalyzerProviderプラグイン 実装 AnalyzerProvider#createAnalyzerを実装するだけ public KuromojiAnalyzerProvider() { super("kuromoji"); // Cypher(クエリ構文)

    オプションで指定する名前 } @Override public Analyzer createAnalyzer() { return new JapaneseAnalyzer(); // Kuromoji } 注意点 • servicesファイルへ実装したクラス • 依存 FQCNを記述 lucene-analysis-kuromoji をNeo4jに同梱する( lucene-core • Neo4j 依存するLucene バージョンと lucene-analysis-kuromoji 同梱しない) バージョンを合わせる 6
  6. 日本語Wikipedia記事で 検証 代表的な 45記事と記事間リンク 371本で検証 // インデックス作成・Analyzer設定 (kuromoji) CREATE FULLTEXT

    INDEX articleJa FOR (a:Article) ON EACH [a.title, a.text] OPTIONS {indexConfig: {`fulltext.analyzer`: 'kuromoji'}}; // 検索 (kuromoji) CALL db.index.fulltext.queryNodes('articleJa', '京都') YIELD node, score RETURN node.title AS title, round(score, 2) AS score LIMIT 5; 上位3件 結果と BM25スコア 比較 順位 kuromoji cjk 1 京都市 2.89 京都市 2.0 2 任天堂 1.35 (本社が京都) 東京都 1.86 (誤ヒット) 3 鹿苑寺 1.17 (金閣寺) 東京タワー 1.64 (誤ヒット) 7
  7. Analyzerをカスタムしてできること JapaneseAnalyzerでできること • 形態素解析による分かち書き(「京都」で「東京都」がヒットするようなノイズが減る) • JapaneseBaseFormFilter による活用形 • JapaneseKatakanaStemFilter で

    • CJKWidthFilter で 原形化(「走っ」→「走る」) 長音除去(「サーバ」で「サーバー」がヒット) 半角全角変換 • JapanesePartOfSpeechStopFilter による助詞・助動詞除去 追加カスタムでできること • lucene-analysis-icu によるICU正規化 • シノニム辞書 活用 8