讓我們在這裡討論即將推出的 FlexSearch v0.8:#415
基本開始 • API 參考 • 文件索引 • 使用 Worker • 變更日誌
您可以透過個人捐款來幫助我,以維持該專案的活力,並提供所有捐款來解決您的需求。
對立營運有限責任公司
就原始搜尋速度而言,FlexSearch 的效能優於現有的所有搜尋庫,並且還提供靈活的搜尋功能,例如多字段搜尋、語音轉換或部分匹配。
根據所使用的選項,它還提供最節省記憶體的索引。 FlexSearch 引入了一種名為「上下文索引」的新評分演算法,該演算法基於預先評分的詞彙詞典架構,與其他庫相比,該架構的查詢速度實際上快了 1,000,000 倍。 FlexSearch 也為您提供非阻塞非同步處理模型以及 Web Worker,以透過專用平衡執行緒並行對索引執行任何更新或查詢。
支援的平台:
圖書館比較《格列佛遊記》:
插件(外部項目):
建造 | 文件 | CDN |
flexsearch.bundle.js | 下載 | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.bundle.js |
flexsearch.light.js | 下載 | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.light.js |
flexsearch.compact.js | 下載 | https://rawcdn.githack.com/nextapps-de/flexsearch/0.7.31/dist/flexsearch.compact.js |
flexsearch.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 支援的 polyfill。
npm install flexsearch
Node.js 套件包含
flexsearch.bundle.js
的所有功能。
特徵 | flexsearch.bundle.js | flexsearch.compact.js | flexsearch.light.js |
預設 | ✓ | ✓ | - |
非同步搜尋 | ✓ | ✓ | - |
工人(Web + Node.js) | ✓ | - | - |
上下文索引 | ✓ | ✓ | ✓ |
索引檔案(實地搜尋) | ✓ | ✓ | - |
文件儲存 | ✓ | ✓ | - |
部分匹配 | ✓ | ✓ | ✓ |
相關性評分 | ✓ | ✓ | ✓ |
按受歡迎程度自動平衡緩存 | ✓ | - | - |
標籤 | ✓ | - | - |
建議 | ✓ | ✓ | - |
拼音匹配 | ✓ | ✓ | - |
可自訂的字元集/語言(匹配器、編碼器、分詞器、詞幹分析器、過濾器、分割、RTL) | ✓ | ✓ | ✓ |
出口/進口指數 | ✓ | - | - |
檔案大小 (gzip) | 6.8 KB | 5.3 KB | 2.9 KB |
運行比較:性能基準“格列佛遊記”
每秒運算元越高越好,除了測試“記憶體”,越低越好。
秩 | 圖書館 | 記憶 | 查詢(單項) | 查詢(多術語) | 查詢(長) | 查詢(重複) | 查詢(未找到) |
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-content-pairs 的扁平高效能索引。Worker
/ WorkerIndex
也是一個平面索引,它儲存 id-content-pairs 但作為專用工作執行緒在後台運行。Document
是多字段索引,可以儲存複雜的JSON文件(也可能存在worker索引)。根據您的情況,大多數人可能只需要其中一個。
< 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-Support。
對
Worker
索引呼叫的每個方法都被視為非同步。您將獲得一個Promise
,或者您也可以提供一個回呼函數作為最後一個參數。
全局方法:
索引方法:
WorkerIndex 方法:
文檔方法:
*對於每個方法都存在一個非同步等效方法:
非同步版本:
非同步方法將傳回Promise
,或者您可以傳遞回呼函數作為最後一個參數。
方法export
和import
始終是非同步的,以及您在基於 Worker 的索引上呼叫的每個方法。
FlexSearch 是高度可自訂的。使用正確的選項可以真正改善您的結果以及記憶體經濟性和查詢時間。
選項 | 價值觀 | 描述 | 預設 |
預設 | “記憶” “表現” “匹配” “分數” "預設" | 設定檔作為快捷方式或作為自訂設定的基礎。 | "預設" |
標記化 | “嚴格的” “向前” "反向" “滿的” | 索引模式(分詞器)。 選擇內建函數之一或傳遞自訂分詞器函數。 | “嚴格的” |
快取 | 布林值 數位 | 啟用/停用和/或設定快取條目的容量。 當傳遞一個數字作為限制時,快取會自動平衡與其受歡迎程度相關的儲存條目。 注意:當僅使用“true”時,快取沒有限制且無限增長。 | 錯誤的 |
解決 | 數位 | 設定評分解析度(預設值:9)。 | 9 |
情境 | 布林值 上下文選項 | 啟用/停用上下文索引。當傳遞“true”作為值時,它將採用上下文的預設值。 | 錯誤的 |
最佳化 | 布林值 | 啟用後,它使用記憶體優化的堆疊流作為索引。 | 真的 |
促進 | 函數(arr,str,int)=>浮點數 | 將內容索引到索引時使用的自訂增強函數。此函數有以下簽名: Function(words[], term, index) => Float 。它有 3 個參數,您可以在其中獲取所有單字的陣列、當前術語以及該術語在單字數組中放置的當前索引。您可以套用自己的計算,例如術語的出現次數並傳回該因子(<1 表示相關性降低,>1 表示相關性增加)。注意:此功能目前僅透過使用分詞器“strict”來限制。 | 無效的 |
特定於語言的選項和編碼: | |||
字元集 | 字符集有效負載 字串(鍵) | 提供自訂字元集有效負載或傳遞內建字元集的鍵之一。 | “拉丁” |
語言 | 語言負載 字串(鍵) | 提供自訂語言負載或傳入內建語言的語言速記標誌 (ISO-3166)。 | 無效的 |
編碼 | 錯誤的 "預設" “簡單的” “平衡” “先進的” “額外的” 函數(str)=> [字] | 編碼類型。 選擇內建函數之一或傳遞自訂編碼函數。 | "預設" |
詞幹分析器 | 錯誤的 細繩 功能 | 錯誤的 | |
篩選 | 錯誤的 細繩 功能 | 錯誤的 | |
匹配器 | 錯誤的 細繩 功能 | 錯誤的 | |
文件索引的其他選項: | |||
勞工 | 布林值 | 啟用/停用並設定正在運行的工作線程的計數。 | 錯誤的 |
文件 | 文檔描述符 | 包括文件索引和儲存的定義。 |
選項 | 價值觀 | 描述 | 預設 |
解決 | 數位 | 設定上下文的評分解析度(預設值:1)。 | 1 |
深度 | 錯誤的 數位 | 啟用/停用上下文索引並設定相關的上下文距離。深度是被認為相關的術語的最大單字/標記數。 | 1 |
雙向 | 布林值 | 設定雙向搜尋結果。如果啟用且原始文字包含“red hat”,則查詢“red hat”和“hat red”時將找到它。 | 真的 |
選項 | 價值觀 | 描述 | 預設 |
ID | 細繩 | “ID”” | |
標籤 | 錯誤的 細繩 | “標籤” | |
指數 | 細繩 數組<字串> 數組<對象> | ||
店鋪 | 布林值 細繩 數組<字串> | 錯誤的 |
選項 | 價值觀 | 描述 | 預設 |
分裂 | 錯誤的 正規表示式 細繩 | 使用非自訂分詞器(內置,例如“forward”)時分割單字的規則。使用字串/字元或使用正規表示式(預設: /W+/ )。 | /[W_]+/ |
回程 | 布林值 | 啟用從右到左編碼。 | 錯誤的 |
編碼 | 函數(str)=> [字] | 自訂編碼功能。 | /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% |
功能() | 透過函數(字串)傳遞自訂編碼:[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++
。
指數。添加(id,字串)
index . add ( 0 , "John Doe" ) ;
指數。搜尋(字串 | 選項,<限制>,<選項>)
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")
時,您將獲得索引 id 1 作為結果中的第一個條目,因為附加資料的上下文從零開始(不會堆疊到舊上下文),而這裡的「index 」 是第一項。
如果您不希望出現此行為,則只需使用標準index.add(id, content)
並提供完整的內容長度。
指數。更新(id,字串)
index . update ( 0 , "Max Miller" ) ;
指數。刪除(id)
index . remove ( 0 ) ;
分詞器將單字/術語拆分為組件或部分。
在建立/初始化期間定義私有自訂標記產生器:
var index = new FlexSearch ( {
tokenize : function ( str ) {
return str . split ( / s-/ / g ) ;
}
} ) ;
tokenizer 函數取得字串作為參數,並且必須傳回表示單字或術語的字串陣列。在某些語言中,每個字元都是一個術語,並且也不用空格分隔。
詞幹分析器:同一單字的幾種語言突變(例如“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 時,至少將分詞器設定為「reverse」或「full」。
只需將欄位“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
分支,而是僅應用更高一級,因此key
成為 options 的主要成員。
對於新語法,字段“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
包含您想要從文件中索引的欄位清單。當只選擇一個欄位時,您可以傳遞一個字串。當也使用預設密鑰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
}
} ]
}
} ) ;
注意:「內容」欄位中的上下文選項也會由對應的欄位選項繼承,而該欄位選項則由全域選項繼承。
假設文件數組看起來更複雜(具有嵌套分支等),例如:
{
"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
} ] ) ;
當文件資料只有一個索引作為外部數組時,您可以跳過第一個循環。
將文檔新增至索引:
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()
將陣列的每個項目新增至自己的上下文時,最後一個條目的相關性將與第一個條目並發。當您在符號中留下括號時,它將把數組連接到一個以空格分隔的字串。這裡第一個條目具有最高的相關性,而最後一個條目具有最低的相關性。
因此,假設上面範例中的關鍵字已根據其受歡迎程度的相關性進行了預先排序,那麼您希望保持此順序(相關性資訊)。為此,請勿在符號中添加括號。否則,它將在新的評分上下文中獲取條目(舊的順序會丟失)。
您還可以保留括號符號以獲得更好的效能和更小的記憶體佔用。當您不需要條目的相關性粒度時可以使用它。
搜尋所有字段:
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
而不是“field”時,您可以明確地僅選擇一個欄位並取得平面表示:
index . search ( query , { pluck : "title" , enrich : true } ) ;
[
{ id : 0 , doc : { /* document */ } } ,
{ id : 1 , doc : { /* document */ } } ,
{ id : 2 , doc : { /* document */ } }
]
此結果集替代了「布林搜尋」。您可以自己在結果集之上動態應用邏輯,而不是將布林邏輯套用到嵌套物件。這極大地提高了您處理結果的能力。因此,字段的結果不再被壓縮為一個結果。這保留了一些重要訊息,例如欄位名稱以及每個欄位結果的相關性,這些資訊不再混合。
預設情況下,欄位搜尋將套用帶有布林「或」邏輯的查詢。對於給定的查詢,每個欄位都有自己的結果。
有一種情況仍然支援bool
屬性。當您想要將預設的“或”邏輯從欄位搜尋切換為“和”時,例如:
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" ]
} ) ;
這將為您提供標有給定標籤之一的結果。
預設情況下,多個標籤將作為布林值「或」套用。它只需要存在一個標籤即可。
這是仍然支援bool
屬性的另一種情況。當您想要將預設的“或”邏輯從標籤搜尋切換為“和”時,例如:
index . search ( query , {
index : "content" ,
tag : [ "dog" , "animal" ] ,
bool : "and"
} ) ;
您將只獲得包含兩個標籤的結果(在本範例中,只有一筆記錄具有標籤「狗」和「動物」)。
當沒有傳遞查詢時,您也可以從一個或多個標籤取得結果:
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 ) ;
您可以獨立配置應索引的內容和應儲存的內容。強烈建議您盡可能使用此功能。
這是配置 doc 和 store 的有用範例:
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]" ,
}
} ]
} ]
「作者」和「電子郵件」欄位均未編入索引。
簡單地連結方法,例如:
var index = FlexSearch . create ( )
. addMatcher ( { 'â' : 'a' } )
. add ( 0 , 'foo' )
. add ( 1 , 'bar' ) ;
index . remove ( 0 ) . update ( 1 , 'foo' ) . add ( 2 , 'foobar' ) ;
注意:此功能預設為停用狀態,因為它會佔用大量記憶體。請閱讀此處以獲取有關以及如何啟用的更多資訊。
FlexSearch 引入了一種稱為上下文搜尋的新評分機制,該機制是由該程式庫的作者 Thomas Wilkerling 發明的。上下文搜尋令人難以置信地將查詢提升到一個全新的水平,但也需要一些額外的記憶體(取決於深度)。這個概念的基本思想是透過上下文來限制相關性,而不是透過其對應文件的整個距離來計算相關性。透過這種方式,上下文搜尋還可以改善對大量文字資料進行基於相關性的查詢的結果。
建立索引並使用預設上下文:
var index = new FlexSearch ( {
tokenize : "strict" ,
context : true
} ) ;
建立索引並為上下文套用自訂選項:
var index = new FlexSearch ( {
tokenize : "strict" ,
context : {
resolution : 5 ,
depth : 3 ,
bidirectional : true
}
} ) ;
上下文索引實際上僅支援“嚴格”分詞器。
上下文索引需要額外的記憶體量,具體取決於深度。
您需要在建立索引期間初始化快取及其限制:
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 (與使用Index
而不是Document
相同)。
用作 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 } ) ;
工作人員將始終以非同步方式執行。在查詢方法呼叫中,您始終應該處理傳回的承諾(例如使用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 ) ;
或者,當所有請求完成後只有一個回呼時,只需使用Promise.all()
它也會優先考慮「所有任務已完成」:
Promise . all ( [
index . searchAsync ( query ) ,
index . searchAsync ( query ) ,
index . searchAsync ( query )
] ) . then ( callback ) ;
在Promise.all()
的回呼中,您還將獲得一個結果數組,分別作為您輸入的每個查詢的第一個參數。
使用await
時,您可以優先考慮順序(優先考慮「第一個任務完成」)並逐一解決請求,然後並行處理子任務:
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)。在工作索引上使用「同步」版本時,內容不會在下面一行索引,因為預設情況下所有呼叫都被視為非同步。
當索引新增/更新/刪除大量內容(或高頻)時,建議將非同步版本與
async/await
一起使用,以在長時間進程中保持較低的記憶體佔用。
出口略有變化。現在的出口由幾個較小的零件組成,而不僅僅是一大堆。您需要傳遞一個回呼函數,該函數有兩個參數“key”和“data”。此回調函數由各個部分調用,例如:
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 中使用或儲存要從伺服器委託給客戶端的索引。
導出的大小對應於庫的記憶體消耗。要減少導出大小,您必須使用記憶體佔用較少的配置(使用底部的表獲取有關配置及其記憶體分配的資訊)。
當您的保存例程非同步運行時,您必須返回一個承諾:
index . export ( function ( key , data ) {
return new Promise ( function ( resolve ) {
// do the saving as async
resolve ( ) ;
} ) ;
} ) ;
您無法匯出「快速更新」功能的附加表。這些表存在引用,存儲時它們完全序列化並變得太大。該庫將自動為您處理這些問題。匯入資料時,索引會自動停用“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 ) ) ;
}
特定於語言的定義分為兩組:
function(string):string[]
boolean
{string: string}
{string: string}
string[]
字元集包含編碼邏輯,語言包含詞幹分析器、停用詞過濾器和匹配器。多種語言定義可以使用相同的字元集編碼器。此外,這種分離還可以讓您管理特殊用例的不同語言定義(例如名稱、城市、方言/俚語等)。
要即時完整地描述自訂語言,您需要傳遞:
const index = FlexSearch ( {
// mandatory:
encode : ( content ) => [ words ] ,
// optionally:
rtl : false ,
stemmer : { } ,
matcher : { } ,
filter : [ ]
} ) ;
當不傳遞參數時,它預設使用latin:default
模式。
場地 | 類別 | 描述 |
編碼 | 字元集 | 編碼器功能。必須傳回分隔單字的陣列(或空字串)。 |
回程 | 字元集 | 指示從右到左編碼的布林屬性。 |
篩選 | 語言 | 過濾器也稱為“停用詞”,它們完全過濾掉被索引的單字。 |
詞幹分析器 | 語言 | 詞幹去除詞尾,是一種「部分規範化」。當單字長度大於匹配的部分時,單字結尾就被匹配。 |
匹配器 | 語言 | 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: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
中的預設管道。它非常簡單直接。管道將作為某種控制反轉進行處理,最終的編碼器實作必須處理字元集以及特定於語言的轉換。此解決方法是許多測試遺留下來的。
透過例如注入預設管道:
this . pipeline (
/* string: */ str . toLowerCase ( ) ,
/* normalize: */ false ,
/* split: */ split ,
/* collapse: */ false
) ;
使用上面的管道模式來理解迭代以及預編碼和後編碼的差異。詞幹分析器和匹配器需要在字元集規範化之後、語言轉換和過濾器之前應用。
這是一個擴展管道的一個很好的例子: src/lang/latin/extra.js
→ src/lang/latin/advanced.js
→ src/lang/latin/simple.js
。
在src/lang/
中搜尋您的語言,如果存在,您可以擴展或提供變體(例如方言/俚語)。如果該語言不存在,請建立新檔案並檢查是否有任何現有字元集(例如拉丁語)適合您的語言。當不存在字元集時,您需要提供一個字元集作為該語言的基礎。
新的字符集至少應提供:
encode
一個函數,它規範化傳遞的文字內容的字元集(刪除特殊字元、語言轉換等)並傳回分隔單字的陣列。這裡還需要應用詞幹分析器、匹配器或停用詞過濾器。當語言沒有單字時,請確保提供類似的內容,例如每個中文符號也可以是一個「單字」。不要傳回未分割的整個文字內容。rtl
一個布林標誌,指示從右到左編碼基本上,字元集只需要提供編碼器函數以及從右到左編碼的指示符:
export function encode ( str ) { return [ str ] }
export const rtl = false ;
參考字串: “Björn-Phillipp Mayer”
詢問 | 預設 | 簡單的 | 先進的 | 額外的 |
比約恩 | 是的 | 是的 | 是的 | 是的 |
比約爾 | 是的 | 是的 | 是的 | 是的 |
比約恩 | 不 | 是的 | 是的 | 是的 |
比約恩 | 不 | 不 | 是的 | 是的 |
菲利普 | 不 | 不 | 是的 | 是的 |
菲利普 | 不 | 不 | 是的 | 是的 |
比約恩菲利普 | 不 | 是的 | 是的 | 是的 |
梅爾 | 不 | 不 | 是的 | 是的 |
比約恩·邁爾 | 不 | 不 | 是的 | 是的 |
梅爾·菲利普 | 不 | 不 | 是的 | 是的 |
拜恩梅爾 | 不 | 不 | 不 | 是的 |
(誤報) | 不 | 不 | 不 | 是的 |
「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
較高的 minlength 將減少記憶體分配:
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 |
快速更新 | +1 | +10(更新、刪除) | 0 | 0 |
優化:真 | -7 | -1 | 0 | -3 |
編碼器:“icase” | 0 | 0 | 0 | 0 |
編碼器:“簡單” | -2 | -1 | +2 | 0 |
編碼器:“高級” | -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 |
商店:真實 | +5(每個文件) | 0 | 0 | 0 |
商店:[字段] | +1(每個欄位) | 0 | 0 | 0 |
快取:真 | +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]
按類別拆分索引可顯著提高效能。
版權所有 2018-2023 Thomas Wilkerling,由 Nextapps GmbH 主辦
根據 Apache 2.0 許可證發布