brief: | 1 i18n.site はサーバーレスの全文検索をサポートするようになりました。

2 i18n.site は、サーバーレスの全文検索をサポートするようになりました。

3 i18n.site は、サーバーレスの全文検索をサポートし、現在、純粋なフロントエンド全文検索を実装しています。


純粋なフロントエンドの逆引き全文検索

順序

数週間の開発を経て、i18n.site(純粋な静的Markdown多言語翻訳およびサイト構築ツール)が、純粋なフロントエンドの全文検索をサポートするようになりました。

本稿では、i18n.siteの純粋なフロントエンド全文検索の技術的実装について詳述し、i18n.siteを訪れることで検索の効果を実感してください。

コードは以下の通りです:検索カーネル / インタラクティブインターフェース

サーバーレス全文検索ソリューションの概要

ドキュメントや個人のブログなど、中小規模の純粋に静的な Web サイトの場合、独自に構築した全文検索バックエンドを構築するのは重すぎるため、サービス不要の全文検索がより一般的な選択肢となります。

11 サーバーレス全文検索ソリューションは大きく二つのカテゴリに分類されます

12 まず、algolia.comなどのサードパーティ検索サービスプロバイダーが、全文検索用のフロントエンドコンポーネントを提供しています。

13 このようなサービスは、検索ボリュームに応じて料金が発生し、ウェブサイトの規制やコンプライアンスの問題により、中国本土のユーザーが利用できないことが多いです。

14 オフラインでの使用やイントラネットでの使用ができず、大きな制限があります。この記事では特に詳しくは触れません。

15 次に、純粋なフロントエンドの全文検索があります。

現在一般的に用いられる純粋なフロントエンド全文検索には、lunrjsElasticLunr.js(lunrjsをベースに二次開発されたもの)があります。

lunrjsのインデックス構築には二つの方法があり、それぞれに問題があります。

  1. 事前構築のインデックスファイル

    19 文書が追加や変更されるたびに、新しいインデックスファイルをロードする必要があります。 20 これにより、ユーザーの待ち時間が長くなり、大量の帯域幅が消費されます。 21 ドキュメントをロードし、その場でインデックスを構築します。

  2. ドキュメントをロードし、その場でインデックスを構築します

    23 lunrjs以外にも、他の全文検索ソリューションがあります。


lunrjs以外にも、以下のような他の全文検索ソリューションがあります:

fusejs 、検索する文字列間の類似性を計算します。

このソリューションのパフォーマンスは非常に低く、全文検索には使用できません (「 Fuse.js長いクエリには10秒以上かかります。最適化するには?」を参照)。

TinySearchは、ブルーム フィルターを使用して検索しますが、接頭辞検索 (たとえば、 gooを入力し、 goodgoogle検索) には使用できず、同様の自動補完効果は得られません。

28 i18n.siteは、以下の特徴を持つ新しい純粋なフロントエンド全文検索ソリューションを提供しています

  1. 多言語検索をサポートし、サイズが小さいです。 gzipパッケージ化した後の検索カーネルのサイズは6.9KBです (比較のために、 lunrjsのサイズは25KBです)
  2. indexedbに基づいて転置インデックスを構築します。これはメモリの使用量が少なく、高速です
  3. ドキュメントが追加/変更された場合、追加または変更されたドキュメントのみが再インデックスされるため、計算量が削減されます
  4. 32 ユーザーが入力中にリアルタイムで検索結果を表示する前方一致検索をサポートします
  5. オフラインで利用可能

以下に、技術実装のi18n.siteを詳しく紹介します。

多言語単語の分割

36 ブラウザのネイティブなIntl.Segmenterを使用して多言語の単語分割を行います。

単語分割coffeescriptコードは次のとおりです

SEG = new Intl.Segmenter 0, granularity: "word"

seg = (txt) =>
  r = []
  for {segment} from SEG.segment(txt)
    for i from segment.split('.')
      i = i.trim()
      if i and !'|`'.includes(i) and !/\p{P}/u.test(i)
        r.push i
  r

export default seg

export segqy = (q) =>
  seg q.toLocaleLowerCase()

で:

インデックスの構築

word : id -

document urlとバージョン番号verの配列を渡し、テーブルdocにドキュメントが存在するかどうかを検索します。存在しない場合は、転置インデックスを作成します。同時に、渡されなかったドキュメントの逆索引を削除します。

49 存在しない場合は、転置インデックスを作成し、渡されなかったドキュメントの逆索引を削除します。

フロントエンド対話では、初回ロード時の遅延を避けるために、インデックスのロード進行状況バーを表示できます。「単一のprogress + Pure css実装に基づくアニメーション付きの進行状況バー」 English / Chinese を参照してください。

IndexedDB の高い同時書き込み

このプロジェクトは、 IndexedDBの非同期カプセル化に基づいてidb

53 競合書き込みによるデータの一部の損失を避けるためには、以下のCoffeeScriptコードを参照してください。

競合書き込みによる部分的なデータ損失を回避するには、以下のcoffeescriptコードを参照し、読み取りと書き込みの間にingキャッシュを追加して競合書き込みを遮断します。

pusher = =>
  ing = new Map()
  (table, id, val)=>
    id_set = ing.get(id)
    if id_set
      id_set.add val
      return

    id_set = new Set([val])
    ing.set id, id_set
    pre = await table.get(id)
    li = pre?.li or []

    loop
      to_add = [...id_set]
      li.push(...to_add)
      await table.put({id,li})
      for i from to_add
        id_set.delete i
      if not id_set.size
        ing.delete id
        break
    return

rindexPush = pusher()
prefixPush = pusher()

オンデマンドロード

60 検索では、まずユーザーが入力したキーワードをセグメント化します。

61 セグメント化された単語がNであると仮定します。結果を返す場合、最初にすべてのキーワードを含む結果が返され、次にN-1N-2、...、1キーワードを含む結果が返されます。

62 最初に表示される検索結果によってクエリの正確さが保証され、その後読み込まれる結果(「さらに読み込む」ボタンをクリック)によって再現率が保証されます。

接頭辞リアルタイム検索

64 応答速度を向上させるために、検索ではyieldジェネレーターを使用してオンデマンド読み込みを実装し、結果がクエリされるたびにlimit結果を返します。

65 yield後に再度検索するたびに、IndexedDBのクエリトランザクションを再度開く必要があります。

プレフィックスリアルタイム検索

ユーザーが入力中に検索結果を表示するため、たとえばworを入力すると、 wordsworkなど先頭にworが付く単語が表示されます。

68 検索カーネルは、単語の分割後の最後の単語に対してprefixテーブルを使用して、その接頭辞が付くすべての単語を検索し、順番に検索します。

手ぶれ補正機能debounceは、検索をトリガーするユーザー入力の頻度を減らし、計算量を減らすために、フロントエンド インタラクション (次のように実装) でも使用されます。

export default (wait, func) => {
  var timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(func.bind(this, ...args), wait);
  };
}

オフラインで利用可能

インデックス テーブルには元のテキストは保存されず、単語のみが保存されるため、ストレージの量が削減されます。

72 同時に、service workerがすべての記事をキャッシュするため、ユーザーが検索を実行すると、検索を含むウェブサイト全体がオフラインで利用できるようになります。

i18n.siteの純粋なフロントエンド検索ソリューションは、Markdownドキュメントに特化しています。

74 検索結果を表示すると、章名が表示され、クリックすると章へ移動します

i18n.siteの純粋なフロントエンド検索ソリューションは、 MarkDownドキュメント用に最適化されています。

要約

要約する

逆引き全文検索は純粋にフロントエンドに実装されており、サーバーは必要ありません。ドキュメントや個人のブログなどの中小規模の Web サイトに非常に適しています。

i18n.siteオープンソースの自社開発の純粋なフロントエンド検索は、サイズが小さく応答が速く、現在の純粋なフロントエンド全文検索の欠点を解決し、より良いユーザー エクスペリエンスを提供します。