0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

パフォーマンス

0
Posted at

🚀 スケールする「知識ベース型メモサービス」の裏側を解説してみる


📌 まず前提:このサービスが解決したい問題

普通のメモアプリは、メモが増えるほどこういう現実的な問題を抱える:

  1. メモが大量になると取得が遅い
    → DB のクエリが増える(N+1問題)

  2. 関連メモの計算が重い
    → embedding 類似度計算やタグ比較は O(N²)

  3. 全文検索が遅い
    → 正規表現ではスケールしない、インデックスが必要

  4. 毎回同じデータを返す API が多い
    → キャッシュ必須(特に Redis)

  5. メモ同士の「意味的な関係」を作りたい
    → embedding + タグでリンク付けする必要がある

  6. グラフ表示(知識グラフ)が重い
    → 大量ノードの位置計算・クラスタリングが必要


🎯 このファイルの目的(最重要ポイント)

ただメモを CRUD するのではなく、
スケールする “知識ベース” を構築するサービス を作ること。

つまり:

  • 高速
  • 賢い検索
  • 意味的に関連するメモ推薦
  • グラフ構造
  • コスト最適化
  • キャッシュで高速化

これらすべてを実現する 高度なメモ処理エンジン がこのサービス。


技術ハイライトを 解説する


1️⃣ N+1問題の解消($lookup / bulkWrite)

🔥 N+1問題とは?

メモを1件取得 → 関連メモを N件クエリする
→ クエリが O(N) 回
超遅くなる


🔥 解決:MongoDB Aggregation $lookup

$lookup: {
  from: 'memos',
  let: { relatedIds: '$related_memo_ids' },
  pipeline: [
    { $match: { $expr: { $in: ['$_id', '$$relatedIds'] } } }
  ],
  as: 'related_memos_data',
}

これにより:

  • 1回のクエリで全部の関連メモを取得可能
  • 速度が劇的に改善(例:1ms → 0.2ms)

🔥 bulkWrite で双方向リンクを一括更新

bulkOps.push({
  updateOne: {
    filter: { _id: otherMemo._id },
    update: { $addToSet: { related_memo_ids: memoId } },
  },
});

大量の更新を 1回の DB リクエスト にまとめる → 高速 & 安定。


2️⃣ 全文検索(text index + relevance score)

MongoDB の text index を使う:

$text: { $search: query }

さらに:

$addFields: { searchScore: { $meta: 'textScore' } }
$sort: { searchScore: -1 }

検索エンジンのような関連度順ソート が簡単にできる。


3️⃣ Redis 多層キャッシュ戦略

キャッシュを「用途別」に分けて TTL 最適化している。

種類 TTL 意味
MEMO_LIST 5分 メモ一覧は頻繁に変わる
MEMO_DETAIL 10分 詳細はそこまで更新されない
RELATED_MEMOS 15分 計算コストが重いため長め
SEARCH 3分 新メモが影響しやすい
TAG_CLOUD 10分 集計コストが高い
STATS 30分 統計はほとんど変わらない

→ データの性質に最適化された TTL が性能を支える。


4️⃣ Embedding とタグで「類似メモ」計算

✔ Embedding 類似度(Cosine Similarity)

cosineSimilarity(embeddingA, embeddingB)

✔ タグ類似度(Jaccard 係数)

intersection / union

✔ 2つを合成して “関連度スコア” を生成

combined = embedding * 0.7 + tag * 0.3

これにより:

  • 意味が似てる → 高スコア
  • タグも同じ → さらに高スコア

Notion AI 風の関連メモ推薦 が可能に。


5️⃣ 知識グラフ(Knowledge Graph)生成

  • ノード = メモ
  • エッジ = 類似度が一定以上のメモ同士(例:0.6 以上)

✔ Force-Directed Layout(物理シミュレーション)

  • ノード同士は反発
  • 関連ノードは引き合う
  • 自然なクラスタリングが生まれる

Obsidian / Notion AI のような知識グラフを再現できる。


6️⃣ Aggregation Pipeline で統計処理を高速化

例:タグ頻度 / 今週のメモ数 / トレンド など

$facet: {
  basic: [...],
  thisWeek: [...],
  topTags: [...],
}

1回のクエリで全統計を取得
→ サーバーもDBも軽くなる


7️⃣ キャッシュ無効化ロジック

変更があり得る部分だけ invalidate:

invalidateMemoCache(userId, memoId)
invalidateUserCache(userId)

→ 全部消さないので高速
→ キャッシュ破綻もしない
→ 一貫して安定した性能を維持


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?