ここで次期 FlexSearch v0.8 について議論しましょう: #415
基本的なスタート • API リファレンス • ドキュメント インデックス • ワーカーの使用 • 変更ログ
このプロジェクトを存続させるため、またあなたのニーズを解決するためにすべての貢献を提供するために、個人的に寄付していただくことで私を助けることができます。
アンチテーゼ オペレーション LLC
生の検索速度に関しては、FlexSearch はあらゆる検索ライブラリを上回り、複数フィールド検索、音声変換、部分一致などの柔軟な検索機能も提供します。
使用するオプションに応じて、最もメモリ効率の高いインデックスも提供します。 FlexSearch は、事前にスコア付けされた語彙辞書アーキテクチャに基づく「コンテキスト インデックス」と呼ばれる新しいスコアリング アルゴリズムを導入しており、実際に他のライブラリと比較して最大 1,000,000 倍高速にクエリを実行します。 FlexSearch は、ノンブロッキングの非同期処理モデルと、専用のバランスの取れたスレッドを通じてインデックスの更新やクエリを並行して実行する Web ワーカーも提供します。
サポートされているプラットフォーム:
図書館比較「ガリバー旅行記」:
プラグイン (外部プロジェクト):
建てる | ファイル | CDN |
フレックスサーチ.バンドル.js | ダウンロード | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.bundle.js |
フレックスサーチ.ライト.js | ダウンロード | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.light.js |
フレックスサーチ.コンパクト.js | ダウンロード | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.compact.js |
フレックスサーチ.es5.js * | ダウンロード | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.es5.js |
ES6 モジュール | ダウンロード | この Github リポジトリの/dist/module/フォルダー |
*バンドル「flexsearch.es5.js」には、EcmaScript 5 サポート用のポリフィルが含まれています。
npm install flexsearch
Node.js パッケージには、
flexsearch.bundle.js
のすべての機能が含まれています。
特徴 | フレックスサーチ.バンドル.js | フレックスサーチ.コンパクト.js | フレックスサーチ.ライト.js |
プリセット | ✓ | ✓ | - |
非同期検索 | ✓ | ✓ | - |
ワーカー (Web + Node.js) | ✓ | - | - |
コンテキストインデックス | ✓ | ✓ | ✓ |
ドキュメントのインデックス作成 (フィールド検索) | ✓ | ✓ | - |
ドキュメントストア | ✓ | ✓ | - |
部分一致 | ✓ | ✓ | ✓ |
関連性スコアリング | ✓ | ✓ | ✓ |
人気による自動バランスキャッシュ | ✓ | - | - |
タグ | ✓ | - | - |
提案 | ✓ | ✓ | - |
音声マッチング | ✓ | ✓ | - |
カスタマイズ可能な文字セット/言語 (マッチャー、エンコーダー、トークナイザー、ステマー、フィルター、分割、RTL) | ✓ | ✓ | ✓ |
インデックスのエクスポート/インポート | ✓ | - | - |
ファイルサイズ (gzip) | 6.8kb | 5.3kb | 2.9kb |
実行比較: パフォーマンスベンチマーク「ガリバー旅行記」
秒あたりの操作量は高いほど優れていますが、テスト「メモリ」は低いほど優れています。
ランク | 図書館 | メモリ | クエリ (単一用語) | クエリ (複数の用語) | クエリ (長い) | クエリ (重複) | クエリ (見つからない) |
1 | フレックスサーチ | 17 | 7084129 | 1586856 | 511585 | 2017142 | 3202006 |
2 | JSii | 27 | 6564 | 158149 | 61290 | 95098 | 534109 |
3 | ウェイド | 424 | 20471 | 78780 | 16693 | 225824 | 213754 |
4 | JS検索 | 193 | 8221 | 64034 | 10377 | 95830 | 167605 |
5 | Elasticlunr.js | 646 | 5412 | 7573 | 2865 | 23786 | 13982 |
6 | 一括検索 | 1021 | 3069 | 3141 | 3333 | 3265 | 21825569 |
7 | ミニサーチ | 24348 | 4406 | 10945 | 72 | 39989 | 17624 |
8 | BM25 | 15719 | 1429 | 789 | 366 | 884 | 1823年 |
9 | Lunr.js | 2219 | 255 | 271 | 272 | 266 | 267 |
10 | ファジーサーチ | 157373 | 53 | 38 | 15 | 32 | 43 |
11 | ヒューズ | 7641904 | 6 | 2 | 1 | 2 | 3 |
インデックスには次の 3 種類があります。
Index
、ID-コンテンツのペアを格納するフラットな高性能インデックスです。Worker
/ WorkerIndex
も、ID-content-pairs を格納するフラット インデックスですが、専用のワーカー スレッドとしてバックグラウンドで実行されます。Document
複雑な JSON ドキュメントを保存できるマルチフィールド インデックスです (ワーカー インデックスも存在する可能性があります)。ほとんどの場合、シナリオに応じてそのうちの 1 つだけが必要になるでしょう。
< script src =" node_modules/flexsearch/dist/flexsearch.bundle.min.js " > </ script >
< script >
// FlexSearch is available on window.FlexSearch
// Access FlexSearch static methods via bundled export (static class methods of FlexSearch)
const index = FlexSearch . Index ( options ) ;
const document = FlexSearch . Document ( options ) ;
const worker = FlexSearch . Worker ( options ) ;
</ script >
< script type =" module " >
// FlexSearch is NOT available on window.FlexSearch
// Access FlexSearch static methods by importing them explicitly
import Index from "./node_modules/flexsearch/dist/module/index" ;
import Document from "./node_modules/flexsearch/dist/module/document" ;
import Worker from "./node_modules/flexsearch/dist/module/worker" ;
const index = new Index ( options ) ;
const document = new Document ( options ) ;
const worker = new Worker ( options ) ;
</ script >
< script type =" module " >
// FlexSearch is NOT available on window.FlexSearch
// Access FlexSearch static methods via bundled export (static class methods of FlexSearch)
import FlexSearch from "./node_modules/flexsearch/dist/flexsearch.bundle.module.min.js" ;
const index = FlexSearch . Index ( options ) ;
const document = FlexSearch . Document ( options ) ;
const worker = FlexSearch . Worker ( options ) ;
</ script >
または CDN 経由:
< script src =" https://cdn.jsdelivr.net/gh/nextapps-de/[email protected]/dist/flexsearch.bundle.min.js " > </ script >
AMD / CommonJS:
var FlexSearch = require ( "./node_modules/flexsearch/dist/flexsearch.bundle.min.js" ) ;
npm install flexsearch
コードには次のように含めます。
const { Index , Document , Worker } = require ( "flexsearch" ) ;
const index = new Index ( options ) ;
const document = new Document ( options ) ;
const worker = new Worker ( options ) ;
または:
const FlexSearch = require ( "flexsearch" ) ;
const index = new FlexSearch . Index ( options ) ;
const document = new FlexSearch . Document ( options ) ;
const worker = new FlexSearch . Worker ( options ) ;
index . add ( id , text ) ;
index . search ( text ) ;
index . search ( text , limit ) ;
index . search ( text , options ) ;
index . search ( text , limit , options ) ;
index . search ( options ) ;
document . add ( doc ) ;
document . add ( id , doc ) ;
document . search ( text ) ;
document . search ( text , limit ) ;
document . search ( text , options ) ;
document . search ( text , limit , options ) ;
document . search ( options ) ;
worker . add ( id , text ) ;
worker . search ( text ) ;
worker . search ( text , limit ) ;
worker . search ( text , options ) ;
worker . search ( text , limit , options ) ;
worker . search ( text , limit , options , callback ) ;
worker . search ( options ) ;
worker
Index
型から継承しますが、 Document
型からは継承しません。したがって、WorkerIndex は基本的に標準の FlexSearch インデックスと同様に機能します。ドキュメント内のワーカー サポートは、作成時に適切なオプション{ worker: true }
を渡すだけで有効にする必要があります。
Worker
インデックスで呼び出されるすべてのメソッドは非同期として扱われます。Promise
を返すか、最後のパラメータとしてコールバック関数を指定することもできます。
グローバルメソッド:
インデックス方法:
WorkerIndex メソッド:
文書化メソッド:
*これらの各メソッドには、同等の非同期メソッドが存在します。
非同期バージョン:
非同期メソッドはPromise
を返しますが、最後のパラメータとしてコールバック関数を渡すこともできます。
export
およびimport
メソッドは、ワーカーベースのインデックスで呼び出すすべてのメソッドと同様に、常に非同期です。
FlexSearch は高度にカスタマイズ可能です。適切なオプションを使用すると、結果だけでなくメモリの節約やクエリ時間も大幅に改善できます。
オプション | 価値観 | 説明 | デフォルト |
プリセット | "メモリ" "パフォーマンス" "マッチ" "スコア" "デフォルト" | ショートカットまたはカスタム設定のベースとしての構成プロファイル。 | "デフォルト" |
トークン化 | "厳しい" "フォワード" "逆行する" "満杯" | インデックス作成モード (トークナイザー)。 組み込みのいずれかを選択するか、カスタム トークナイザー関数を渡します。 | "厳しい" |
キャッシュ | ブール値 番号 | キャッシュされたエントリの有効化/無効化、および/または容量の設定。 制限として数値を渡すと、キャッシュは人気度に関連して保存されたエントリのバランスを自動的にとります。 注: 「true」のみを使用する場合、キャッシュには制限がなく、無制限に増加します。 | 間違い |
解決 | 番号 | スコアリングの解像度を設定します (デフォルト: 9)。 | 9 |
コンテクスト | ブール値 コンテキストオプション | コンテキストインデックスを有効/無効にします。値として「true」を渡すと、コンテキストのデフォルト値が使用されます。 | 間違い |
最適化する | ブール値 | 有効にすると、インデックスにメモリ最適化スタック フローが使用されます。 | 真実 |
ブースト | function(arr, str, int) => float | コンテンツをインデックスに登録するときに使用されるカスタム ブースト関数。関数には次のシグネチャがあります: Function(words[], term, index) => Float 。これには、すべての単語の配列、現在の用語、および単語配列内で用語が配置されている現在のインデックスを取得する 3 つのパラメーターがあります。独自の計算 (用語の出現など) を適用して、この係数を返すことができます (<1 は関連性が低いことを意味し、>1 は関連性が高いことを意味します)。注: この機能は現在、トークナイザー「strict」の使用のみに制限されています。 | ヌル |
言語固有のオプションとエンコーディング: | |||
文字セット | 文字セットペイロード 文字列(キー) | カスタム文字セット ペイロードを提供するか、組み込み文字セットのキーの 1 つを渡します。 | "ラテン" |
言語 | 言語ペイロード 文字列(キー) | カスタム言語ペイロードを提供するか、組み込み言語の言語短縮フラグ (ISO-3166) を渡します。 | ヌル |
エンコード | 間違い "デフォルト" "単純" "バランス" "高度な" "余分な" 関数(文字列) => [単語] | エンコードタイプ。 組み込みのいずれかを選択するか、カスタム エンコード関数を渡します。 | "デフォルト" |
ステマー | 間違い 弦 関数 | 間違い | |
フィルター | 間違い 弦 関数 | 間違い | |
マッチャー | 間違い 弦 関数 | 間違い | |
ドキュメントインデックスの追加オプション: | |||
ワーカー | ブール値 | 実行中のワーカー スレッドの有効化/無効化と数の設定。 | 間違い |
書類 | 文書記述子 | ドキュメントのインデックスとストレージの定義が含まれます。 |
オプション | 価値観 | 説明 | デフォルト |
解決 | 番号 | コンテキストのスコアリング解像度を設定します (デフォルト: 1)。 | 1 |
深さ | 間違い 番号 | コンテキストのインデックス作成を有効/無効にし、コンテキストの関連性の距離も設定します。深さは、用語から関連性があるとみなされる単語/トークンの最大数です。 | 1 |
双方向 | ブール値 | 双方向の検索結果を設定します。有効で、ソース テキストに「red hat」が含まれている場合、クエリ「red hat」および「hat red」で検索されます。 | 真実 |
オプション | 価値観 | 説明 | デフォルト |
ID | 弦 | 「ID」 | |
タグ | 間違い 弦 | "タグ" | |
索引 | 弦 配列<文字列> 配列<オブジェクト> | ||
店 | ブール値 弦 配列<文字列> | 間違い |
オプション | 価値観 | 説明 | デフォルト |
スプリット | 間違い 正規表現 弦 | 非カスタムトークナイザー (「forward」などの組み込み) を使用する場合に単語を分割するルール。文字列/文字、または正規表現 (デフォルト: /W+/ ) を使用します。 | /[W_]+/ |
rtl | ブール値 | 右から左へのエンコードを有効にします。 | 間違い |
エンコード | 関数(文字列) => [単語] | カスタムエンコード関数。 | /lang/latin/default.js |
オプション | 価値観 | 説明 |
ステマー | 間違い 弦 関数 | 無効にするか、言語短縮フラグ (ISO-3166) またはカスタム オブジェクトを渡します。 |
フィルター | 間違い 弦 関数 | 無効にするか、言語短縮フラグ (ISO-3166) またはカスタム配列を渡します。 |
マッチャー | 間違い 弦 関数 | 無効にするか、言語短縮フラグ (ISO-3166) またはカスタム配列を渡します。 |
オプション | 価値観 | 説明 | デフォルト |
限界 | 番号 | 結果の制限を設定します。 | 100 |
オフセット | 番号 | オフセットを適用します(項目をスキップします)。 | 0 |
提案する | ブール値 | 結果での提案を有効にします。 | 間違い |
オプション | 価値観 | 説明 | デフォルト |
索引 | 弦 配列<文字列> 配列<オブジェクト> | 検索する必要があるドキュメントフィールドを設定します。フィールドが設定されていない場合は、すべてのフィールドが検索されます。フィールドごとのカスタム オプションもサポートされています。 | |
タグ | 弦 配列<文字列> | 検索する必要があるドキュメントフィールドを設定します。フィールドが設定されていない場合は、すべてのフィールドが検索されます。フィールドごとのカスタム オプションもサポートされています。 | 間違い |
豊かにする | ブール値 | 対応するドキュメントを使用して結果から ID を強化します。 | 間違い |
ブール | "そして" "または" | 複数のフィールドまたはタグを検索するときに使用する論理演算子を設定します。 | "または" |
トークナイザーは、クエリ時間や部分一致の柔軟性など、必要なメモリにも影響を与えます。ニーズに合ったこれらのトークナイザーの中で最も上位のものを選択してください。
オプション | 説明 | 例 | 記憶係数 (n = 単語の長さ) |
"厳しい" | 単語全体のインデックスを付ける | foobar | ※1 |
"フォワード" | 単語を順方向に増分インデックス化する | fo foob あーる | *n |
"逆行する" | 単語のインデックスを両方向に増分的に作成する | ふーぶar obar | * 2n - 1 |
"満杯" | 可能なすべての組み合わせにインデックスを付けます | oba oob | * n * (n - 1) |
エンコーディングは、クエリ時間や音声一致としても必要なメモリに影響します。これらのエンコーダーの中でニーズに合ったものを選択するか、カスタム エンコーダーを渡してみてください。
オプション | 説明 | 誤検知 | 圧縮 |
間違い | エンコードをオフにする | いいえ | 0% |
"デフォルト" | 大文字と小文字を区別しないエンコーディング | いいえ | 0% |
"単純" | 大文字と小文字を区別しないエンコーディング 文字セットの正規化 | いいえ | ~ 3% |
"バランス" | 大文字と小文字を区別しないエンコーディング 文字セットの正規化 リテラル変換 | いいえ | ~ 30% |
"高度な" | 大文字と小文字を区別しないエンコーディング 文字セットの正規化 リテラル変換 音声の正規化 | いいえ | ~ 40% |
"余分な" | 大文字と小文字を区別しないエンコーディング 文字セットの正規化 リテラル変換 音声の正規化 Soundex 変換 | はい | ~ 65% |
関数() | function(string):[words]経由でカスタム エンコーディングを渡す |
var index = new Index ( ) ;
新しいインデックスを作成し、プリセットのいずれかを選択します。
var index = new Index ( "performance" ) ;
カスタム オプションを使用して新しいインデックスを作成します。
var index = new Index ( {
charset : "latin:extra" ,
tokenize : "reverse" ,
resolution : 9
} ) ;
新しいインデックスを作成し、カスタム オプションを使用してプリセットを拡張します。
var index = new FlexSearch ( {
preset : "memory" ,
tokenize : "forward" ,
resolution : 5
} ) ;
利用可能なカスタム オプションをすべて表示します。
インデックスに追加するすべてのコンテンツには ID が必要です。コンテンツに ID がない場合は、インデックス、カウント、またはその他のものを ID として渡して ID を作成する必要があります (タイプnumber
の値を強くお勧めします)。これらの ID は、特定のコンテンツへの一意の参照です。これは、既存の ID を使用してコンテンツを更新または追加する場合に重要です。参照が問題でない場合は、 count++
のような単純なものを使用できます。
索引。 add(id, 文字列)
index . add ( 0 , "John Doe" ) ;
索引。 search(文字列 | オプション, <制限>, <オプション>)
index . search ( "John" ) ;
結果を制限する:
index . search ( "John" , 10 ) ;
ID が既にインデックス付けされているかどうかは、次の方法で確認できます。
if ( index . contain ( 1 ) ) {
console . log ( "ID is already in index" ) ;
}
各メソッドは、その非同期バージョンで呼び出すことができます (例: index.addAsync
またはindex.searchAsync
。
各非同期関数にコールバックを割り当てることができます。
index . addAsync ( id , content , function ( ) {
console . log ( "Task Done" ) ;
} ) ;
index . searchAsync ( query , function ( result ) {
console . log ( "Results: " , result ) ;
} ) ;
または、コールバック関数を渡さず、代わりにPromise
返します。
index . addAsync ( id , content ) . then ( function ( ) {
console . log ( "Task Done" ) ;
} ) ;
index . searchAsync ( query ) . then ( function ( result ) {
console . log ( "Results: " , result ) ;
} ) ;
または、 async
とawait
使用します。
async function add ( ) {
await index . addAsync ( id , content ) ;
console . log ( "Task Done" ) ;
}
async function search ( ) {
const results = await index . searchAsync ( query ) ;
console . log ( "Results: " , result ) ;
}
次のように既存のインデックスにコンテンツを追加できます。
index . append ( id , content ) ;
これはindex.update(id, content)
実行する場合のように、古いインデックス付きコンテンツを上書きしません。 id が既にインデックス付けされている場合、 index.add(id, content)
内部で「更新」も実行することに注意してください。
追加されたコンテンツには独自のコンテキストと独自の完全なresolution
があります。したがって、関連性は積み重ねられず、独自のコンテキストを取得します。
次の例を見てみましょう。
index . add ( 0 , "some index" ) ;
index . append ( 0 , "some appended content" ) ;
index . add ( 1 , "some text" ) ;
index . append ( 1 , "index appended content" ) ;
index.search("index")
クエリすると、追加されたデータのコンテキストは 0 から始まり (古いコンテキストにスタックされない)、ここでは "index" であるため、結果の最初のエントリとしてインデックス ID 1 が取得されます。 』が第一期です。
この動作を望まない場合は、標準のindex.add(id, content)
使用して、コンテンツの完全な長さを指定するだけです。
索引。 update(id, 文字列)
index . update ( 0 , "Max Miller" ) ;
索引。削除(ID)
index . remove ( 0 ) ;
トークナイザーは、単語/用語をコンポーネントまたは部分部分に分割します。
作成/初期化中にプライベート カスタム トークナイザーを定義します。
var index = new FlexSearch ( {
tokenize : function ( str ) {
return str . split ( / s-/ / g ) ;
}
} ) ;
トークナイザー関数はパラメーターとして文字列を取得し、単語または用語を表す文字列の配列を返す必要があります。一部の言語では、すべての文字が用語であり、空白で区切られていません。
ステマー:同じ単語の複数の言語的変異 (例: 「run」と「running」)
フィルター:インデックス作成から除外される単語のブラックリスト (例: "and"、"to"、または "be")
作成/初期化中にプライベートのカスタム ステマーまたはフィルターを割り当てます。
var index = new FlexSearch ( {
stemmer : {
// object {key: replacement}
"ational" : "ate" ,
"tional" : "tion" ,
"enci" : "ence" ,
"ing" : ""
} ,
filter : [
// array blacklist
"in" ,
"into" ,
"is" ,
"isn't" ,
"it" ,
"it's"
]
} ) ;
カスタム フィルターの使用:
var index = new FlexSearch ( {
filter : function ( value ) {
// just add values with length > 1 to the index
return value . length > 1 ;
}
} ) ;
または、ステマー/フィルターを言語にグローバルに割り当てます。
ステマーはオブジェクト (キーと値のペア) として渡され、フィルターは配列として渡されます。
FlexSearch . registerLanguage ( "us" , {
stemmer : { /* ... */ } ,
filter : [ /* ... */ ]
} ) ;
または、事前に定義されたステマーや好みの言語のフィルターを使用します。
< html >
< head >
< script src =" js/flexsearch.bundle.js " > </ script >
< script src =" js/lang/en.min.js " > </ script >
< script src =" js/lang/de.min.js " > </ script >
</ head >
...
作成/初期化中に組み込みステマーを割り当てることができるようになりました。
var index_en = new FlexSearch . Index ( {
language : "en"
} ) ;
var index_de = new FlexSearch . Index ( {
language : "de"
} ) ;
Node.js では、すべての組み込み言語パック ファイルが利用可能です。
const { Index } = require ( "flexsearch" ) ;
var index_en = new Index ( {
language : "en"
} ) ;
RTL を使用する場合は、トークナイザーを少なくとも「リバース」または「フル」に設定します。
「rtl」フィールドをtrueに設定し、互換性のあるトークナイザーを使用するだけです。
var index = new Index ( {
encode : str => str . toLowerCase ( ) . split ( / [^a-z]+ / ) ,
tokenize : "reverse" ,
rtl : true
} ) ;
ニーズに合ったカスタム トークナイザーを設定します。例:
var index = FlexSearch . create ( {
encode : str => str . replace ( / [x00-x7F] / g , "" ) . split ( "" )
} ) ;
カスタム エンコーダ関数を渡して言語変換を適用することもできます。
index . add ( 0 , "一个单词" ) ;
var results = index . search ( "单词" ) ;
ドキュメントが次のようなデータ構造を持つと仮定します。
{
"id" : 0 ,
"content" : " some text "
}
古い構文 FlexSearch v0.6.3 (サポートされなくなりました! ):
const index = new Document ( {
doc : {
id : "id" ,
field : [ "content" ]
}
} ) ;
ドキュメント記述子はわずかに変更されており、
field
分岐はなくなり、代わりに 1 つ上のレベルを適用するだけなので、key
オプションの主要メンバーになります。
新しい構文では、フィールド「doc」の名前がdocument
に変更され、フィールド「field」の名前がindex
に変更されました。
const index = new Document ( {
document : {
id : "id" ,
index : [ "content" ]
}
} ) ;
index . add ( {
id : 0 ,
content : "some text"
} ) ;
フィールドid
ID または一意のキーがドキュメント内のどこに存在するかを示します。デフォルトのキーが渡されない場合、デフォルトで値id
が取得されるため、上記の例を次のように短縮できます。
const index = new Document ( {
document : {
index : [ "content" ]
}
} ) ;
メンバーindex
ドキュメントからインデックスを作成するフィールドのリストが含まれています。フィールドを 1 つ選択するだけの場合は、文字列を渡すことができます。デフォルトのキーid
も使用する場合、これは次のように短縮されます。
const index = new Document ( { document : "content" } ) ;
index . add ( { id : 0 , content : "some text" } ) ;
複数のフィールドがある場合、インデックスに複数のフィールドを追加できます。
var docs = [ {
id : 0 ,
title : "Title A" ,
content : "Body A"
} , {
id : 1 ,
title : "Title B" ,
content : "Body B"
} ] ;
const index = new Document ( {
id : "id" ,
index : [ "title" , "content" ]
} ) ;
各フィールドにカスタム オプションを渡すことができます。
const index = new Document ( {
id : "id" ,
index : [ {
field : "title" ,
tokenize : "forward" ,
optimize : true ,
resolution : 9
} , {
field : "content" ,
tokenize : "strict" ,
optimize : true ,
resolution : 5 ,
minlength : 3 ,
context : {
depth : 1 ,
resolution : 3
}
} ]
} ) ;
フィールド オプションは、グローバル オプションも渡された場合に継承されます。例:
const index = new Document ( {
tokenize : "strict" ,
optimize : true ,
resolution : 9 ,
document : {
id : "id" ,
index : [ {
field : "title" ,
tokenize : "forward"
} , {
field : "content" ,
minlength : 3 ,
context : {
depth : 1 ,
resolution : 3
}
} ]
}
} ) ;
注: フィールド「content」のコンテキスト オプションも対応するフィールド オプションによって継承されますが、このフィールド オプションはグローバル オプションによって継承されます。
ドキュメント配列がより複雑に見える (ネストされた分岐などがある) と仮定します。例:
{
"record" : {
"id" : 0 ,
"title" : " some title " ,
"content" : {
"header" : " some text " ,
"footer" : " some text "
}
}
}
次に、コロン区切り表記root:child:child
使用して、ドキュメント記述子内の階層を定義します。
const index = new Document ( {
document : {
id : "record:id" ,
index : [
"record:title" ,
"record:content:header" ,
"record:content:footer"
]
}
} ) ;
クエリを実行するフィールドを追加するだけです。インデックスにフィールドを追加しないでください。フィールドは結果に必要なだけです (クエリは実行しませんでした)。この目的のために、ドキュメントをそのインデックスとは独立して保存できます (以下を参照)。
フィールドを介してクエリを実行する場合は、 doc
で定義したフィールドの正確なキーをフィールド名として (コロン構文を使用して) 渡す必要があります。
index . search ( query , {
index : [
"record:title" ,
"record:content:header" ,
"record:content:footer"
]
} ) ;
以下と同じ:
index . search ( query , [
"record:title" ,
"record:content:header" ,
"record:content:footer"
] ) ;
フィールド固有のオプションを使用する:
index . search ( [ {
field : "record:title" ,
query : "some query" ,
limit : 100 ,
suggest : true
} , {
field : "record:title" ,
query : "some other query" ,
limit : 100 ,
suggest : true
} ] ) ;
同じフィールドに対して異なるクエリを使用して検索を実行できます。
フィールド固有のオプションを渡す場合は、各フィールドの完全な構成を指定する必要があります。これらは文書記述子のように継承されません。
書類に関しては次の 2 つのルールに従う必要があります。
[ // <-- not allowed as document start!
{
"id" : 0 ,
"title" : "title"
}
]
{
"records" : [ // <-- not allowed when ID or tag lives inside!
{
"id" : 0 ,
"title" : "title"
}
]
}
サポートされている複雑なドキュメントの例を次に示します。
{
"meta" : {
"tag" : " cat " ,
"id" : 0
},
"contents" : [
{
"body" : {
"title" : " some title " ,
"footer" : " some text "
},
"keywords" : [ " some " , " key " , " words " ]
},
{
"body" : {
"title" : " some title " ,
"footer" : " some text "
},
"keywords" : [ " some " , " key " , " words " ]
}
]
}
対応するドキュメント記述子 (すべてのフィールドにインデックスを付ける必要がある場合) は次のようになります。
const index = new Document ( {
document : {
id : "meta:id" ,
tag : "meta:tag" ,
index : [
"contents[]:body:title" ,
"contents[]:body:footer" ,
"contents[]:keywords"
]
}
} ) ;
繰り返しますが、検索するときは、フィールド定義と同じコロンで区切られた文字列を使用する必要があります。
index . search ( query , {
index : "contents[]:body:title"
} ) ;
この例では、上記のルールを両方とも破ります。
[ // <-- not allowed as document start!
{
"tag" : "cat" ,
"records" : [ // <-- not allowed when ID or tag lives inside!
{
"id" : 0 ,
"body" : {
"title" : "some title" ,
"footer" : "some text"
} ,
"keywords" : [ "some" , "key" , "words" ]
} ,
{
"id" : 1 ,
"body" : {
"title" : "some title" ,
"footer" : "some text"
} ,
"keywords" : [ "some" , "key" , "words" ]
}
]
}
]
何らかの構造正規化を適用する必要があります。
このようなデータ構造に対する回避策は次のようになります。
const index = new Document ( {
document : {
id : "record:id" ,
tag : "tag" ,
index : [
"record:body:title" ,
"record:body:footer" ,
"record:body:keywords"
]
}
} ) ;
function add ( sequential_data ) {
for ( let x = 0 , data ; x < sequential_data . length ; x ++ ) {
data = sequential_data [ x ] ;
for ( let y = 0 , record ; y < data . records . length ; y ++ ) {
record = data . records [ y ] ;
index . add ( {
id : record . id ,
tag : data . tag ,
record : record
} ) ;
}
}
}
// now just use add() helper method as usual:
add ( [ {
// sequential structured data
// take the data example above
} ] ) ;
ドキュメント データの外部配列としてインデックスが 1 つだけある場合は、最初のループをスキップできます。
ドキュメントをインデックスに追加します。
index . add ( {
id : 0 ,
title : "Foo" ,
content : "Bar"
} ) ;
単一のオブジェクトまたはオブジェクトの配列を使用してインデックスを更新します。
index . update ( {
data : {
id : 0 ,
title : "Foo" ,
body : {
content : "Bar"
}
}
} ) ;
単一のオブジェクトまたはオブジェクトの配列をインデックスから削除します。
index . remove ( docs ) ;
ID がわかっている場合は、次の方法で簡単に (より速く) 削除することもできます。
index . remove ( id ) ;
上記の複雑な例では、フィールドのkeywords
は配列ですが、ここではマークアップにkeywords[]
のような括弧がありません。これにより配列も検出されますが、各エントリを新しいコンテキストに追加する代わりに、配列は大きな文字列に結合され、インデックスに追加されます。
両方の種類の配列内容の追加の違いは、検索時の関連性です。構文field[]
使用して、 append()
経由で配列の各項目を独自のコンテキストに追加する場合、最初のエントリと同時に発生する最後のエントリの関連性。表記内で括弧を残すと、配列が空白で区切られた 1 つの文字列に結合されます。ここでは、最初のエントリの関連性が最も高く、最後のエントリの関連性が最も低くなります。
したがって、上記の例のキーワードが人気との関連性によって事前に並べ替えられていると仮定すると、この順序 (関連性の情報) を維持する必要があります。この目的のために、表記に括弧を追加しないでください。それ以外の場合、エントリは新しいスコアリング コンテキストで取得されます (古い順序は失われます)。
また、パフォーマンスを向上させ、メモリ使用量を小さくするために括弧表記を残すこともできます。エントリによる関連性の粒度が必要ない場合に使用します。
すべてのフィールドを検索します。
index . search ( query ) ;
特定のフィールドを検索します。
index . search ( query , { index : "title" } ) ;
指定された一連のフィールドを検索します。
index . search ( query , { index : [ "title" , "content" ] } ) ;
以下と同じ:
index . search ( query , [ "title" , "content" ] ) ;
カスタム修飾子とクエリを各フィールドに渡します。
index . search ( [ {
field : "content" ,
query : "some query" ,
limit : 100 ,
suggest : true
} , {
field : "content" ,
query : "some other query" ,
limit : 100 ,
suggest : true
} ] ) ;
同じフィールドに対して異なるクエリを使用して検索を実行できます。
利用可能なフィールド検索オプションをすべて表示します。
結果セットのスキーマ:
fields[] => { field, result[] => { document }}
最初のインデックスは、クエリが適用されたフィールドの配列です。このフィールドのそれぞれには、「フィールド」と「結果」という 2 つのプロパティを持つレコード (オブジェクト) があります。 「結果」も配列であり、この特定のフィールドの結果が含まれます。結果は、ID の配列、または保存されたドキュメント データで強化されたものになる可能性があります。
強化されていない結果セットは次のようになります。
[ {
field : "title" ,
result : [ 0 , 1 , 2 ]
} , {
field : "content" ,
result : [ 3 , 4 , 5 ]
} ]
強化された結果セットは次のようになります。
[ {
field : "title" ,
result : [
{ id : 0 , doc : { /* document */ } } ,
{ id : 1 , doc : { /* document */ } } ,
{ id : 2 , doc : { /* document */ } }
]
} , {
field : "content" ,
result : [
{ id : 3 , doc : { /* document */ } } ,
{ id : 4 , doc : { /* document */ } } ,
{ id : 5 , doc : { /* document */ } }
]
} ]
「フィールド」の代わりにpluck
使用すると、フィールドを 1 つだけ明示的に選択して、フラットな表現を取得できます。
index . search ( query , { pluck : "title" , enrich : true } ) ;
[
{ id : 0 , doc : { /* document */ } } ,
{ id : 1 , doc : { /* document */ } } ,
{ id : 2 , doc : { /* document */ } }
]
この結果セットは、「ブール検索」に代わるものです。ブール ロジックをネストされたオブジェクトに適用する代わりに、結果セットの上に自分でロジックを動的に適用できます。これにより、結果を処理する方法が大幅に可能になります。したがって、フィールドからの結果が 1 つの結果にまとめられることはなくなりました。これにより、フィールドの名前や各フィールドの結果の関連性などの重要な情報が保持され、混在することはなくなりました。
フィールド検索では、デフォルトでブール値の「or」ロジックを使用したクエリが適用されます。各フィールドには、指定されたクエリに対する独自の結果が含まれます。
bool
プロパティがまだサポートされている状況が 1 つあります。フィールド検索のデフォルトの「or」ロジックを「and」に切り替えたい場合は、次のようにします。
index . search ( query , {
index : [ "title" , "content" ] ,
bool : "and"
} ) ;
両方のフィールドにクエリを含む結果のみが得られます。それでおしまい。
ID のkey
と同様に、タグへのパスを定義するだけです。
const index = new Document ( {
document : {
id : "id" ,
tag : "tag" ,
index : "content"
}
} ) ;
index . add ( {
id : 0 ,
tag : "cat" ,
content : "Some content ..."
} ) ;
データには複数のタグを配列として含めることもできます。
index . add ( {
id : 1 ,
tag : [ "animal" , "dog" ] ,
content : "Some content ..."
} ) ;
次の方法でタグ固有の検索を実行できます。
index . search ( query , {
index : "content" ,
tag : "animal"
} ) ;
これにより、指定されたタグが付けられた結果が得られるだけです。
検索するときは複数のタグを使用します。
index . search ( query , {
index : "content" ,
tag : [ "cat" , "dog" ]
} ) ;
これにより、指定されたタグのいずれかでタグ付けされた結果が得られます。
複数のタグはデフォルトでブール値「or」として適用されます。いずれかのタグが存在する必要があるだけです。
これは、 bool
プロパティがまだサポートされている別の状況です。タグ検索のデフォルトの「or」ロジックを「and」に切り替えたい場合は、次のようにします。
index . search ( query , {
index : "content" ,
tag : [ "dog" , "animal" ] ,
bool : "and"
} ) ;
両方のタグを含む結果が得られます (この例では、「犬」と「動物」のタグを持つレコードが 1 つだけあります)。
クエリが渡されなかった場合、1 つ以上のタグから結果をフェッチすることもできます。
index . search ( { tag : [ "cat" , "dog" ] } ) ;
この場合、結果セットは次のようになります。
[ {
tag : "cat" ,
result : [ /* all cats */ ]
} , {
tag : "dog" ,
result : [ /* all dogs */ ]
} ]
デフォルトでは、各クエリは 100 エントリに制限されています。無制限のクエリは問題を引き起こします。サイズを調整するには、オプションとして制限を設定する必要があります。
各クエリの制限とオフセットを設定できます。
index . search ( query , { limit : 20 , offset : 100 } ) ;
結果セットのサイズを事前にカウントすることはできません。これは FlexSearch の設計による制限です。ページングできるすべての結果の数が本当に必要な場合は、十分に高い制限を割り当ててすべての結果を取得し、ページング オフセットを手動で適用します (これはサーバー側でも機能します)。 FlexSearch は十分に高速であるため、これは問題になりません。
ドキュメントインデックスのみがストアを持つことができます。 ID コンテンツのペアのみを保存する場合にも、フラット インデックスの代わりにドキュメント インデックスを使用してこの機能を利用できます。
どのフィールドにインデックスを付け、どのフィールドを保存するかを個別に定義できます。このようにして、検索結果に含めるべきではないフィールドにインデックスを付けることができます。
次の場合には、ストアを使用しないでください。 1. 結果として ID の配列が十分に良好である場合、または 2. すでにコンテンツ/ドキュメントが別の場所 (インデックスの外側) に保存されている場合。
store
属性が設定されている場合は、明示的に保存する必要があるすべてのフィールドを含める必要があります (ホワイトリストのように機能します)。
store
属性が設定されていない場合は、元のドキュメントがフォールバックとして保存されます。
これにより、元のコンテンツ全体がストアに追加されます。
const index = new Document ( {
document : {
index : "content" ,
store : true
}
} ) ;
index . add ( { id : 0 , content : "some text" } ) ;
インデックス付きドキュメントはストアから取得できます。
var data = index . get ( 1 ) ;
次の方法で、インデックスを変更せずにストアの内容を直接更新/変更できます。
index . set ( 1 , data ) ;
ストアを更新し、インデックスも更新するには、単にindex.update
、 index.add
、またはindex.append
使用します。
クエリを実行すると、それがドキュメント インデックスであるかフラット インデックスであるかにかかわらず、常に ID の配列が返されます。
オプションで、次の方法で、保存されたコンテンツを使用してクエリ結果を自動的に強化できます。
index . search ( query , { enrich : true } ) ;
結果は次のようになります。
[ {
id : 0 ,
doc : { /* content from store */ }
} , {
id : 1 ,
doc : { /* content from store */ }
} ]
これにより、ドキュメントの特定のフィールドのみがストアに追加されます (ID をストアに保持する必要はありません)。
const index = new Document ( {
document : {
index : "content" ,
store : [ "author" , "email" ]
}
} ) ;
index . add ( id , content ) ;
何をインデックス化し、何を保存するかを個別に構成できます。可能な限りこれを利用することを強くお勧めします。
ここでは、ドキュメントとストアを構成する便利な例を示します。
const index = new Document ( {
document : {
index : "content" ,
store : [ "author" , "email" ]
}
} ) ;
index . add ( {
id : 0 ,
author : "Jon Doe" ,
email : "[email protected]" ,
content : "Some content for the index ..."
} ) ;
コンテンツに対してクエリを実行すると、代わりに保存された値が返されます。
index . search ( "some content" , { enrich : true } ) ;
結果は次のようになります。
[ {
field : "content" ,
result : [ {
id : 0 ,
doc : {
author : "Jon Doe" ,
email : "[email protected]" ,
}
} ]
} ]
「author」フィールドと「email」フィールドは両方ともインデックス付けされていません。
次のようなメソッドを連鎖させるだけです。
var index = FlexSearch . create ( )
. addMatcher ( { 'â' : 'a' } )
. add ( 0 , 'foo' )
. add ( 1 , 'bar' ) ;
index . remove ( 0 ) . update ( 1 , 'foo' ) . add ( 2 , 'foobar' ) ;
注:この機能はメモリ使用量が増えるため、デフォルトでは無効になっています。詳細と有効化方法については、ここをお読みください。
FlexSearch には、このライブラリの作成者である Thomas Wilkerling が発明したContextual Searchと呼ばれる新しいスコアリング メカニズムが導入されています。コンテキスト検索は、クエリをまったく新しいレベルまで驚くほど強化しますが、追加のメモリも必要になります (深さに応じて)。この概念の基本的な考え方は、対応するドキュメントの距離全体を通じて関連性を計算するのではなく、コンテキストによって関連性を制限することです。このようにして、コンテキスト検索によって、大量のテキスト データに対する関連性ベースのクエリの結果も向上します。
インデックスを作成し、デフォルトのコンテキストを使用します。
var index = new FlexSearch ( {
tokenize : "strict" ,
context : true
} ) ;
インデックスを作成し、コンテキストのカスタム オプションを適用します。
var index = new FlexSearch ( {
tokenize : "strict" ,
context : {
resolution : 5 ,
depth : 3 ,
bidirectional : true
}
} ) ;
実際にコンテキスト インデックスでサポートされるのはトークナイザー「strict」のみです。
コンテキストインデックスには、深さに応じて追加のメモリが必要です。
インデックスの作成時にキャッシュとその制限を初期化する必要があります。
const index = new Index ( { cache : 100 } ) ;
const results = index . searchCache ( query ) ;
キャッシュを使用する一般的なシナリオは、入力時のオートコンプリートまたはインスタント検索です。
制限として数値を渡すと、キャッシュは人気度に関連して保存されたエントリのバランスを自動的にとります。
「true」だけを使用すると、キャッシュに制限がなく、実際に 2 ~ 3 倍高速に実行されます (バランサーを実行する必要がないため)。
v0.7.0 からの新しいワーカー モデルは、ドキュメントの「フィールド」に分割されています (1 ワーカー = 1 フィールド インデックス)。このようにして、ワーカーはタスク (サブタスク) を完全に解決できるようになります。このパラダイムの欠点は、コンテンツを格納する際に完全なバランスが取れていない可能性があることです (フィールドのコンテンツの長さが異なる場合があります)。一方で、ストレージのバランスをとることが何らかの利点をもたらすという兆候はありません (すべてのストレージに合計で同じ量が必要です)。
ドキュメントインデックスを使用する場合は、オプション「worker」を適用するだけです。
const index = new Document ( {
index : [ "tag" , "name" , "title" , "text" ] ,
worker : true
} ) ;
index . add ( {
id : 1 , tag : "cat" , name : "Tom" , title : "some" , text : "some"
} ) . add ( {
id : 2 , tag : "dog" , name : "Ben" , title : "title" , text : "content"
} ) . add ( {
id : 3 , tag : "cat" , name : "Max" , title : "to" , text : "to"
} ) . add ( {
id : 4 , tag : "dog" , name : "Tim" , title : "index" , text : "index"
} ) ;
Worker 1: { 1: "cat", 2: "dog", 3: "cat", 4: "dog" }
Worker 2: { 1: "Tom", 2: "Ben", 3: "Max", 4: "Tim" }
Worker 3: { 1: "some", 2: "title", 3: "to", 4: "index" }
Worker 4: { 1: "some", 2: "content", 3: "to", 4: "index" }
すべてのフィールドでフィールド検索を実行すると、このタスクはすべてのワーカーで完全にバランスが取れ、サブタスクを個別に解決できます。
上記では、ドキュメントがフィールドごとにワーカーを自動的に作成することを見てきました。 WorkerIndex を直接作成することもできます ( Document
の代わりにIndex
使用するのと同じです)。
ES6 モジュールとして使用:
import WorkerIndex from "./worker/index.js" ;
const index = new WorkerIndex ( options ) ;
index . add ( 1 , "some" )
. add ( 2 , "content" )
. add ( 3 , "to" )
. add ( 4 , "index" ) ;
または、代わりにバンドル バージョンが使用された場合:
var index = new FlexSearch . Worker ( options ) ;
index . add ( 1 , "some" )
. add ( 2 , "content" )
. add ( 3 , "to" )
. add ( 4 , "index" ) ;
このような WorkerIndex は、 Index
の作成されたインスタンスとほぼ同じように機能します。
WorkerIndex は、すべてのメソッドの
async
バリアントのみをサポートします。つまり、WorkerIndex でindex.search()
を呼び出すと、index.searchAsync()
と同じ方法で非同期でも実行されます。
Node.js のワーカー モデルは「ワーカー スレッド」に基づいており、まったく同じように動作します。
const { Document } = require ( "flexsearch" ) ;
const index = new Document ( {
index : [ "tag" , "name" , "title" , "text" ] ,
worker : true
} ) ;
または、非ドキュメント インデックス用に単一のワーカー インスタンスを作成します。
const { Worker } = require ( "flexsearch" ) ;
const index = new Worker ( { options } ) ;
ワーカーは常に非同期として実行されます。クエリメソッドの呼び出しでは、常に返された Promise を処理するか (例: await
を使用)、コールバック関数を最後のパラメータとして渡す必要があります。
const index = new Document ( {
index : [ "tag" , "name" , "title" , "text" ] ,
worker : true
} ) ;
すべてのリクエストとサブタスクは並行して実行されます (「すべてのタスクの完了」が優先されます)。
index . searchAsync ( query , callback ) ;
index . searchAsync ( query , callback ) ;
index . searchAsync ( query , callback ) ;
また (「すべてのタスクが完了したこと」を優先します):
index . searchAsync ( query ) . then ( callback ) ;
index . searchAsync ( query ) . then ( callback ) ;
index . searchAsync ( query ) . then ( callback ) ;
または、すべてのリクエストが完了したときにコールバックが 1 つだけの場合は、単純にPromise.all()
を使用します。これも「すべてのタスクの完了」を優先します。
Promise . all ( [
index . searchAsync ( query ) ,
index . searchAsync ( query ) ,
index . searchAsync ( query )
] ) . then ( callback ) ;
Promise.all()
のコールバック内では、入力した各クエリの最初のパラメーターとして結果の配列も取得します。
await
使用すると、順序に優先順位を付け (「最初のタスクの完了」を優先)、リクエストを 1 つずつ解決し、サブタスクを並行して処理することができます。
await index . searchAsync ( query ) ;
await index . searchAsync ( query ) ;
await index . searchAsync ( query ) ;
index.add()
、 index.append()
、 index.remove()
またはindex.update()
についても同様です。ここにはライブラリによって無効にされない特殊なケースがありますが、Workers を使用する場合は注意する必要があります。
ワーカー インデックスで「同期」バージョンを呼び出すと、次のようになります。
index . add ( doc ) ;
index . add ( doc ) ;
index . add ( doc ) ;
// contents aren't indexed yet,
// they just queued on the message channel
もちろん、そうすることもできますが、メインスレッドには分散ワーカータスク用の追加のキューがないことに注意してください。これらを長いループで実行すると、内部でworker.postMessage()
を介してメッセージ チャネルにコンテンツが大量に送信されます。幸いなことに、ブラウザーと Node.js は、そのような受信タスクを自動的に処理します (十分な空き RAM が利用可能である限り)。ワーカー インデックスで「同期」バージョンを使用する場合、デフォルトではすべての呼び出しが非同期として扱われるため、コンテンツは 1 行下にインデックス付けされません。
大量のコンテンツをインデックス (または高頻度) に追加/更新/削除する場合は、長時間のプロセス中にメモリ フットプリントを低く保つために、
async/await
とともに async バージョンを使用することをお勧めします。
エクスポートは若干変更されました。エクスポートは、1 つの大きなバルクだけではなく、いくつかの小さなパーツで構成されるようになりました。 「key」と「data」の 2 つの引数を持つコールバック関数を渡す必要があります。このコールバック関数は各部分によって呼び出されます。例:
index . export ( function ( key , data ) {
// you need to store both the key and the data!
// e.g. use the key for the filename and save your data
localStorage . setItem ( key , data ) ;
} ) ;
データを localStorage にエクスポートすることは実際には良い方法ではありませんが、サイズが問題にならない場合は、必要に応じて使用してください。エクスポートは主に、Node.js で使用するため、またはサーバーからクライアントに委任するインデックスを保存するために存在します。
エクスポートのサイズは、ライブラリのメモリ消費量に対応します。エクスポート サイズを減らすには、メモリ フットプリントの少ない構成を使用する必要があります (構成とそのメモリ割り当てに関する情報を取得するには、下部の表を使用してください)。
保存ルーチンが非同期で実行される場合は、Promise を返す必要があります。
index . export ( function ( key , data ) {
return new Promise ( function ( resolve ) {
// do the saving as async
resolve ( ) ;
} ) ;
} ) ;
「fastupdate」機能の追加テーブルをエクスポートすることはできません。これらのテーブルは参照で存在し、保存されると完全にシリアル化され、大きくなりすぎます。ライブラリはこれらを自動的に処理します。データをインポートするとき、インデックスは自動的に「fastupdate」を無効にします。
データをインポートする前に、まずインデックスを作成する必要があります。ドキュメント インデックスには、データのエクスポート時に使用したのと同じドキュメント記述子を提供します。この構成はエクスポートには保存されません。
var index = new Index ( { ... } ) ;
データをインポートするには、キーとデータを渡すだけです。
index . import ( key , localStorage . getItem ( key ) ) ;
すべてのキーをインポートする必要があります。そうしないと、インデックスが機能しません。エクスポートからのキーを保存し、このキーをインポートに使用する必要があります (キーの順序は異なる場合があります)。
これはデモ用であり、インポートとしてサポートされていない他のキーが localStorage に存在する可能性があるため、推奨されません。
var keys = Object . keys ( localStorage ) ;
for ( let i = 0 , key ; i < keys . length ; i ++ ) {
key = keys [ i ] ;
index . import ( key , localStorage . getItem ( key ) ) ;
}
言語固有の定義は 2 つのグループに分けられます。
function(string):string[]
boolean
{string: string}
{string: string}
string[]
文字セットにはエンコード ロジックが含まれ、言語にはステマー、ストップワード フィルター、マッチャーが含まれます。複数の言語定義で同じ文字セット エンコーダを使用できます。また、この分離により、特殊な使用例 (名前、都市、方言/スラングなど) に応じてさまざまな言語定義を管理できます。
オンザフライでカスタム言語を完全に記述するには、以下を渡す必要があります。
const index = FlexSearch ( {
// mandatory:
encode : ( content ) => [ words ] ,
// optionally:
rtl : false ,
stemmer : { } ,
matcher : { } ,
filter : [ ]
} ) ;
パラメータを渡さない場合、デフォルトでlatin:default
スキーマが使用されます。
分野 | カテゴリ | 説明 |
エンコード | 文字セット | エンコーダー機能です。区切られた単語の配列 (または空の文字列) を返す必要があります。 |
rtl | 文字セット | 右から左へのエンコーディングを示すブール型プロパティ。 |
フィルター | 言語 | フィルターは「ストップワード」とも呼ばれ、インデックス付けから単語を完全に除外します。 |
ステマー | 言語 | ステマーは語尾を削除するもので、「部分正規化」の一種です。単語の長さが一致した部分文字より大きい場合に一致した単語末尾。 |
マッチャー | 言語 | Matcher は、その位置に関係なく、指定された文字列の出現箇所をすべて置き換えます。また、一種の「部分正規化」でもあります。 |
モジュールを介して文字セット/言語固有のエンコーディングを割り当てる最も簡単な方法は次のとおりです。
import charset from "./dist/module/lang/latin/advanced.js" ;
import lang from "./dist/module/lang/en.js" ;
const index = FlexSearch ( {
charset : charset ,
lang : lang
} ) ;
各モジュールごとにデフォルトのエクスポートをインポートし、それに応じて割り当てるだけです。
上記の完全修飾例は次のとおりです。
import { encode , rtl } from "./dist/module/lang/latin/advanced.js" ;
import { stemmer , filter , matcher } from "./dist/module/lang/en.js" ;
const index = FlexSearch ( {
encode : encode ,
rtl : rtl ,
stemmer : stemmer ,
matcher : matcher ,
filter : filter
} ) ;
上の例は、少なくとも各文字セット/言語からエクスポートされた標準インターフェイスです。
エンコーダを直接定義して、他のオプションをすべて残すこともできます。
import simple from "./dist/module/lang/latin/simple.js" ;
const index = FlexSearch ( {
encode : simple
} ) ;
初期化中に文字セットを渡すことによって、文字セットを割り当てることができます。たとえば、デフォルトの文字セット エンコーダの場合はcharset: "latin"
、エンコーダ バリアントの場合はcharset: "latin:soundex"
です。
言語定義 (特にマッチャー) を使用して、特定の言語の方言やスラングを正規化することもできます。
次の方法で文字セットや言語定義を利用できるようにする必要があります。
flexsearch.bundle.js
ビルドに含まれますが、言語固有の定義は含まれません/dist/lang/
にあるパッケージをロードできます (ファイルは言語を指し、フォルダーは文字セットを指します)言語パックをロードするときは、次の前にライブラリがロードされていることを確認してください。
< script src =" dist/flexsearch.light.js " > </ script >
< script src =" dist/lang/latin/default.min.js " > </ script >
< script src =" dist/lang/en.min.js " > </ script >
完全な「バンドル」バージョンを使用する場合、組み込みのラテン語エンコーダーがすでに含まれており、言語ファイルをロードするだけで済みます。
< script src =" dist/flexsearch.bundle.js " > </ script >
< script src =" dist/lang/en.min.js " > </ script >
パックを外部パッケージ (非 ES6 モジュール) としてロードするため、ショートカットで初期化する必要があります。
const index = FlexSearch ( {
charset : "latin:soundex" ,
lang : "en"
} ) ;
charset:variant
表記を使用して、charset とそのバリアントを割り当てます。バリアントなしでcharsetを通過するだけの場合、charset:default
として自動的に解決されます。
既存の定義をオーバーライドすることもできます。
const index = FlexSearch ( {
charset : "latin" ,
lang : "en" ,
matcher : { }
} ) ;
渡された定義はデフォルトの定義を拡張せず、それらを置き換えます。
定義を拡張したい場合は、新しい言語ファイルを作成してすべてのロジックを入力してください。
エンコーダーバリアントを使用すると、かなり簡単です。
< script src =" dist/flexsearch.light.js " > </ script >
< script src =" dist/lang/latin/advanced.min.js " > </ script >
< script src =" dist/lang/latin/extra.min.js " > </ script >
< script src =" dist/lang/en.min.js " > </ script >
完全な「バンドル」バージョンを使用する場合、組み込みのラテンエンコーダーはすでに含まれており、言語ファイルをロードする必要があります。
< script src =" dist/flexsearch.bundle.js " > </ script >
< script src =" dist/lang/en.min.js " > </ script >
const index_advanced = FlexSearch ( {
charset : "latin:advanced"
} ) ;
const index_extra = FlexSearch ( {
charset : "latin:extra"
} ) ;
FlexSearchでは、コアユニットへの直接的な依存関係であるため、独自の部分トークン剤を提供することはできません。 FlexSearchの組み込みトークンザーは、各単語を異なるパターンでフラグメントに分割します。
これは、FlexSearchが提供するデフォルトのパイプラインです。
最初は、 src/common.js
のデフォルトのパイプラインをご覧ください。それは非常にシンプルで率直です。パイプラインは、制御の何らかの反転として処理され、最終的なエンコーダーの実装はcharsetと言語固有の変換を処理する必要があります。この回避策は、多くのテストから残っています。
例:デフォルトのパイプラインを注入します。
this . pipeline (
/* string: */ str . toLowerCase ( ) ,
/* normalize: */ false ,
/* split: */ split ,
/* collapse: */ false
) ;
上からのパイプラインスキーマを使用して、エンコード前とエンコード後の反復と違いを理解します。 STEMMERとMATCHERSは、charSetの正規化後ではなく、言語変換の前にフィルターを適用する必要があります。
パイプラインを拡張する良い例を示します: src/lang/latin/extra.js
→ src/lang/latin/advanced.js
→ src/lang/latin/simple.js
。
src/lang/
で言語を検索してください。存在する場合は、バリアント(方言/スラングなど)を拡張または提供できます。言語が存在しない場合、新しいファイルを作成し、既存の充電器(ラテン語など)のいずれかが言語に適合するかどうかを確認します。 charsetが存在しない場合、言語のベースとしてcharsetを提供する必要があります。
新しいチャーセットは、少なくとも次のことを提供する必要があります。
encode
、分離された単語の配列を返します。また、Stemmer、Matcher、またはStopwordフィルターをここに適用する必要があります。言語に言葉がない場合、同様のものを確実に提供するようにしてください。分割せずにテキストコンテンツ全体を返さないでください。rtl
左から左のエンコーディングを示すブールフラグ基本的に、charsetは、右から左のエンコードのインジケータとともにエンコーダー関数を提供するためだけに必要です。
export function encode ( str ) { return [ str ] }
export const rtl = false ;
参照文字列: 「Björn-Phillipp Mayer」
クエリ | デフォルト | 単純 | 高度な | 余分な |
ビョルン | はい | はい | はい | はい |
björ | はい | はい | はい | はい |
ビョルン | いいえ | はい | はい | はい |
bjoern | いいえ | いいえ | はい | はい |
フィリップ | いいえ | いいえ | はい | はい |
フィリップ | いいえ | いいえ | はい | はい |
Björnphillip | いいえ | はい | はい | はい |
マイヤー | いいえ | いいえ | はい | はい |
BjörnMeier | いいえ | いいえ | はい | はい |
Meier fhilip | いいえ | いいえ | はい | はい |
Byorn Mair | いいえ | いいえ | いいえ | はい |
(偽陽性) | いいえ | いいえ | いいえ | はい |
「Gulliver's Travels Swift Jonathan 1726」という本は、以下の例については完全にインデックス付けされていました。
最もメモリ最適化された意味のある設定は、本全体にわずか1.2 MBを割り当てます!これはおそらく、検索ライブラリから入手できる最も小さなメモリフットプリントです。
import { encode } from "./lang/latin/extra.js" ;
index = new Index ( {
encode : encode ,
tokenize : "strict" ,
optimize : true ,
resolution : 1 ,
minlength : 3 ,
fastupdate : false ,
context : false
} ) ;
「ガリバーの旅行」(Swift Jonathan 1726)という本は、このテストのために完全に索引付けされました。
デフォルトでは、語彙インデックスは非常に小さいです:
depth: 0, bidirectional: 0, resolution: 3, minlength: 0
=> 2.1 mb
解像度が高いとメモリの割り当てが増加します。
depth: 0, bidirectional: 0, resolution: 9, minlength: 0
=> 2.9 mb
コンテキストインデックスを使用すると、メモリの割り当てが増加します。
depth: 1, bidirectional: 0, resolution: 9, minlength: 0
=> 12.5 mb
コンテキストの深さが高いと、メモリの割り当てが増加します。
depth: 2, bidirectional: 0, resolution: 9, minlength: 0
=> 21.5 mb
より高い最小長さはメモリの割り当てを減少させます:
depth: 2, bidirectional: 0, resolution: 9, minlength: 3
=> 19.0 mb
双方向を使用すると、メモリの割り当てが減少します。
depth: 2, bidirectional: 1, resolution: 9, minlength: 3
=> 17.9 mb
オプション「FastUpDate」を有効にすると、メモリの割り当てが増加します。
depth: 2, bidirectional: 1, resolution: 9, minlength: 3
=> 6.3 mb
すべての検索ライブラリは、これらの4つのプロパティと常に競合しています。
FlexSearchは、特定のユースケースの最適バランスを調整するために使用できる多くのパラメーターを提供します。
修飾子 | メモリインパクト * | パフォーマンスインパクト** | マッチングインパクト** | スコアリングインパクト** |
解決 | +1(レベルごと) | +1(レベルごと) | 0 | +2(レベルごと) |
深さ | +4(レベルごと) | -1(レベルごと) | -10 +深さ | +10 |
最小長さ | -2(レベルごと) | +2(レベルごと) | -3(レベルごと) | +2(レベルごと) |
双方向 | -2 | 0 | +3 | -1 |
FastUpDate | +1 | +10(更新、削除) | 0 | 0 |
最適化:true | -7 | -1 | 0 | -3 |
エンコーダー:「ICase」 | 0 | 0 | 0 | 0 |
エンコーダ:「シンプル」 | -2 | -1 | +2 | 0 |
エンコーダ:「Advanced」 | -3 | -2 | +4 | 0 |
エンコーダ:「エクストラ」 | -5 | -5 | +6 | 0 |
エンコーダ:「SoundEx」 | -6 | -2 | +8 | 0 |
トークン化:「厳格」 | 0 | 0 | 0 | 0 |
トークン化:「フォワード」 | +3 | -2 | +5 | 0 |
トークン化:「逆」 | +5 | -4 | +7 | 0 |
トークン化:「フル」 | +8 | -5 | +10 | 0 |
ドキュメントインデックス | +3(フィールドごと) | -1(フィールドごと) | 0 | 0 |
ドキュメントタグ | +1(タグごと) | -1(タグごと) | 0 | 0 |
ストア:true | +5(ドキュメントごと) | 0 | 0 | 0 |
ストア:[フィールド] | +1(フィールドごと) | 0 | 0 | 0 |
キャッシュ: true | +10 | +10 | 0 | 0 |
キャッシュ:100 | +1 | +9 | 0 | 0 |
IDのタイプ:番号 | 0 | 0 | 0 | 0 |
IDのタイプ:文字列 | +3 | -3 | 0 | 0 |
memory
(プライマリメモリの最適化)performance
(パフォーマンスのためのプライマリ最適化)match
(一致するためにプライマリ最適化)score
(スコアリングに最適化するプライマリ)default
(デフォルトのバランスプロファイル)これらのプロファイルは、標準的なユースケースをカバーしています。あなたの状況に最適なものを得るためにプロファイルを使用するのではなく、カスタム構成を適用することをお勧めします。すべてのプロファイルは、極端なパフォーマンス最適化された構成や極端なメモリなど、特定のタスク、その他のタスクにさらに最適化できます。
インデックスの作成/初期化中にプリセットを渡すことができます。
インデックスにコンテンツを追加するときに、参照として数値ID値を使用することをお勧めします。合格したIDのバイトの長さは、メモリ消費に大きく影響します。これが不可能な場合は、インデックステーブルを使用してインデックスを使用してIDをマッピングすることを検討する必要があります。これは、特に大量のコンテンツでコンテキストインデックスを使用する場合に重要になります。
できる限り、コンテンツをカテゴリごとに分割し、独自のインデックスに追加してみてください。
var action = new FlexSearch ( ) ;
var adventure = new FlexSearch ( ) ;
var comedy = new FlexSearch ( ) ;
これにより、各カテゴリに異なる設定を提供することもできます。これは、実際にはファジー検索を実行する最速の方法です。
この回避策をより拡張可能にするには、短いヘルパーを使用できます。
var index = { } ;
function add ( id , cat , content ) {
( index [ cat ] || (
index [ cat ] = new FlexSearch
) ) . add ( id , content ) ;
}
function search ( cat , query ) {
return index [ cat ] ?
index [ cat ] . search ( query ) : [ ] ;
}
インデックスにコンテンツを追加します:
add ( 1 , "action" , "Movie Title" ) ;
add ( 2 , "adventure" , "Movie Title" ) ;
add ( 3 , "comedy" , "Movie Title" ) ;
クエリを実行する:
var results = search ( "action" , "movie title" ) ; // --> [1]
カテゴリごとにインデックスを分割すると、パフォーマンスが大幅に向上します。
Copyright 2018-2023 Thomas Wilkerling、NextApps GmbHがホスト
Apache 2.0ライセンスの下でリリースされました