มาพูดคุยถึง FlexSearch v0.8 ที่กำลังจะมาถึงที่นี่: #415
การเริ่มต้นขั้นพื้นฐาน • การอ้างอิง API • ดัชนีเอกสาร • การใช้พนักงาน • บันทึกการเปลี่ยนแปลง
คุณสามารถช่วยฉันได้ด้วยการบริจาคส่วนตัวเพื่อให้โครงการนี้คงอยู่ต่อไปได้ และยังบริจาคเงินทั้งหมดเพื่อแก้ไขความต้องการของคุณอีกด้วย
Antithesis Operations LLC
เมื่อพูดถึงความเร็วในการค้นหาแบบดิบ FlexSearch มีประสิทธิภาพเหนือกว่าไลบรารีการค้นหาทุกแห่งที่มีอยู่ และยังให้ความสามารถในการค้นหาที่ยืดหยุ่น เช่น การค้นหาแบบหลายฟิลด์ การแปลงการออกเสียง หรือการจับคู่บางส่วน
ขึ้นอยู่กับตัวเลือกที่ใช้ ยังให้ดัชนีประสิทธิภาพหน่วยความจำสูงสุดอีกด้วย FlexSearch แนะนำอัลกอริธึมการให้คะแนนใหม่ที่เรียกว่า "ดัชนีบริบท" ตามสถาปัตยกรรมพจนานุกรมคำศัพท์ที่ให้คะแนนไว้ล่วงหน้า ซึ่งดำเนินการสืบค้นได้เร็วกว่าถึง 1,000,000 เท่าเมื่อเทียบกับไลบรารีอื่น ๆ FlexSearch ยังมอบโมเดลการประมวลผลแบบอะซิงโครนัสที่ไม่มีการบล็อก รวมถึงผู้ปฏิบัติงานเว็บเพื่อทำการอัปเดตหรือสืบค้นดัชนีแบบขนานผ่านเธรดที่สมดุลโดยเฉพาะ
แพลตฟอร์มที่รองรับ:
การเปรียบเทียบห้องสมุด "การเดินทางของกัลลิเวอร์":
ปลั๊กอิน (โครงการภายนอก):
สร้าง | ไฟล์ | ซีดีเอ็น |
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 | ดาวน์โหลด | โฟลเดอร์ /dist/module/ ของที่เก็บ Github นี้ |
* บันเดิล "flexsearch.es5.js" มี polyfills สำหรับการรองรับ EcmaScript 5
npm install flexsearch
แพ็คเกจ Node.js มีฟีเจอร์ทั้งหมดจาก
flexsearch.bundle.js
คุณสมบัติ | flexsearch.bundle.js | flexsearch.compact.js | flexsearch.light.js |
ค่าที่ตั้งล่วงหน้า | - | ||
การค้นหาแบบอะซิงโครนัส | - | ||
ผู้ปฏิบัติงาน (เว็บ + Node.js) | - | - | |
ดัชนีบริบท | |||
เอกสารดัชนี (ค้นหาภาคสนาม) | - | ||
ร้านขายเอกสาร | - | ||
การจับคู่บางส่วน | |||
การให้คะแนนความเกี่ยวข้อง | |||
แคชอัตโนมัติที่สมดุลตามความนิยม | - | - | |
แท็ก | - | - | |
ข้อเสนอแนะ | - | ||
การจับคู่สัทศาสตร์ | - | ||
ชุดอักขระ/ภาษาที่ปรับแต่งได้ (Matcher, Encoder, Tokenizer, Stemmer, Filter, Split, RTL) | |||
ดัชนีการส่งออก / นำเข้า | - | - | |
ขนาดไฟล์ (gzip) | 6.8 กิโลไบต์ | 5.3 กิโลไบต์ | 2.9 กิโลไบต์ |
เปรียบเทียบการดำเนินการ: เกณฑ์มาตรฐานประสิทธิภาพ "การเดินทางของกัลลิเวอร์"
การทำงานต่อวินาที สูงกว่าจะดีกว่า ยกเว้นการทดสอบ "หน่วยความจำ" ซึ่งต่ำกว่าจะดีกว่า
อันดับ | ห้องสมุด | หน่วยความจำ | แบบสอบถาม (ระยะเดียว) | แบบสอบถาม (หลายคำ) | แบบสอบถาม (ยาว) | แบบสอบถาม (ซ้ำซ้อน) | แบบสอบถาม (ไม่พบ) |
1 | FlexSearch | 17 | 7084129 | 1586856 | 511585 | 2017142 | 3202006 |
2 | เจสซี่ | 27 | 6564 | 158149 | 61290 | 95098 | 534109 |
3 | ลุย | 424 | 20471 | 78780 | 16693 | 225824 | 213754 |
4 | เจเอสค้นหา | 193 | 8221 | 64034 | 10377 | 95830 | 167605 |
5 | Elasticlunr.js | 646 | 5412 | 7573 | 2865 | 23786 | 13982 |
6 | ค้นหาเป็นกลุ่ม | 1,021 | 3069 | 3141 | 3333 | 3265 | 21825569 |
7 | มินิค้นหา | 24348 | 4406 | 10945 | 72 | 39989 | 17624 |
8 | บีเอ็ม25 | 15719 | 1429 | 789 | 366 | 884 | 1823 |
9 | Lunr.js | 2219 | 255 | 271 | 272 | 266 | 267 |
10 | FuzzySearch | 157373 | 53 | 38 | 15 | 32 | 43 |
11 | ฟิวส์ | 7641904 | 6 | 2 | 1 | 2 | 3 |
ดัชนีมี 3 ประเภท:
Index
เป็นดัชนีประสิทธิภาพสูงแบบแบนซึ่งจัดเก็บคู่ id-content-pairWorker
/ WorkerIndex
ยังเป็นดัชนีแบบเรียบซึ่งจัดเก็บคู่ id-content-pair แต่ทำงานในพื้นหลังเป็นเธรดของผู้ปฏิบัติงานเฉพาะDocument
เป็นดัชนีแบบหลายฟิลด์ซึ่งสามารถจัดเก็บเอกสาร JSON ที่ซับซ้อนได้ (อาจมีดัชนีผู้ปฏิบัติงานอยู่ด้วย)พวกคุณส่วนใหญ่อาจต้องการเพียงหนึ่งในนั้นตามสถานการณ์ของคุณ
< 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 >
เอเอ็มดี / 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:
วิธีการจัดทำเอกสาร:
* สำหรับแต่ละวิธีจะมีค่าเทียบเท่าแบบอะซิงโครนัส:
เวอร์ชันอะซิงก์:
วิธีการ Async จะส่งคืน Promise
หรือคุณสามารถส่งฟังก์ชันการโทรกลับเป็นพารามิเตอร์สุดท้ายได้
วิธี export
และ import
จะเป็นแบบอะซิงก์เสมอ เช่นเดียวกับทุกวิธีที่คุณเรียกใช้ในดัชนีผู้ปฏิบัติงาน
FlexSearch สามารถปรับแต่งได้สูง การใช้ตัวเลือกที่เหมาะสมสามารถปรับปรุงผลลัพธ์ของคุณได้จริง เช่นเดียวกับการประหยัดหน่วยความจำและเวลาในการสืบค้น
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
ที่ตั้งไว้ล่วงหน้า | "หน่วยความจำ" "ผลงาน" "จับคู่" "คะแนน" "ค่าเริ่มต้น" | โปรไฟล์การกำหนดค่าเป็นทางลัดหรือเป็นฐานสำหรับการตั้งค่าที่คุณกำหนดเอง | "ค่าเริ่มต้น" |
โทเค็น | "เข้มงวด" "ซึ่งไปข้างหน้า" "ย้อนกลับ" "เต็ม" | โหมดการจัดทำดัชนี (tokenizer) เลือกหนึ่งในบิวด์อินหรือส่งฟังก์ชันโทเค็นไนเซอร์แบบกำหนดเอง | "เข้มงวด" |
แคช | บูลีน ตัวเลข | เปิด/ปิดใช้งาน และ/หรือตั้งค่าความจุของรายการแคช เมื่อส่งผ่านตัวเลขเป็นขีดจำกัด แคชจะปรับสมดุลรายการที่จัดเก็บซึ่งเกี่ยวข้องกับความนิยมโดยอัตโนมัติ หมายเหตุ: เมื่อใช้เพียง "true" แคชจะไม่มีขีดจำกัดและการเติบโตไม่มีขอบเขต | เท็จ |
ปณิธาน | ตัวเลข | ตั้งค่าความละเอียดการให้คะแนน (ค่าเริ่มต้น: 9) | 9 |
บริบท | บูลีน ตัวเลือกบริบท | เปิด/ปิดการจัดทำดัชนีตามบริบท เมื่อส่งค่า "จริง" จะใช้ค่าเริ่มต้นสำหรับบริบท | เท็จ |
ปรับให้เหมาะสม | บูลีน | เมื่อเปิดใช้งาน จะใช้โฟลว์สแต็กที่ปรับให้เหมาะสมสำหรับหน่วยความจำสำหรับดัชนี | จริง |
เพิ่ม | ฟังก์ชั่น (arr, str, int) => float | ฟังก์ชันบูสต์แบบกำหนดเองที่ใช้เมื่อจัดทำดัชนีเนื้อหาลงในดัชนี ฟังก์ชั่นมีลายเซ็นนี้: Function(words[], term, index) => Float มีพารามิเตอร์ 3 ตัวที่คุณได้รับอาร์เรย์ของคำทั้งหมด คำศัพท์ปัจจุบันและดัชนีปัจจุบันที่คำศัพท์นั้นวางอยู่ในอาร์เรย์คำ คุณสามารถใช้การคำนวณของคุณเอง เช่น การเกิดขึ้นของคำและส่งกลับปัจจัยนี้ (<1 หมายถึงความเกี่ยวข้องลดลง >1 หมายถึงความเกี่ยวข้องเพิ่มขึ้น)หมายเหตุ: ขณะนี้คุณลักษณะนี้ถูกจำกัดโดยใช้โทเค็นไนเซอร์ "เข้มงวด" เท่านั้น | โมฆะ |
ตัวเลือกและการเข้ารหัสเฉพาะภาษา: | |||
ชุดอักขระ | Charset เพย์โหลด สตริง (คีย์) | ระบุเพย์โหลดชุดอักขระที่กำหนดเองหรือส่งหนึ่งในคีย์ของชุดอักขระในตัว | "ละติน" |
ภาษา | เพย์โหลดภาษา สตริง (คีย์) | ระบุเพย์โหลดภาษาที่กำหนดเองหรือส่งผ่านธงชวเลขภาษา (ISO-3166) ของภาษาที่มีอยู่แล้วภายใน | โมฆะ |
เข้ารหัส | เท็จ "ค่าเริ่มต้น" "เรียบง่าย" "สมดุล" "ขั้นสูง" "พิเศษ" ฟังก์ชั่น (str) => [คำ] | ประเภทการเข้ารหัส เลือกหนึ่งในบิวด์อินหรือส่งฟังก์ชันการเข้ารหัสแบบกำหนดเอง | "ค่าเริ่มต้น" |
ลำต้น | เท็จ สตริง การทำงาน | เท็จ | |
กรอง | เท็จ สตริง การทำงาน | เท็จ | |
เครื่องจับคู่ | เท็จ สตริง การทำงาน | เท็จ | |
ตัวเลือกเพิ่มเติมสำหรับดัชนีเอกสาร: | |||
คนงาน | บูลีน | เปิด/ปิดใช้งานและตั้งค่าจำนวนเธรดของผู้ปฏิบัติงานที่ทำงานอยู่ | เท็จ |
เอกสาร | ตัวอธิบายเอกสาร | รวมคำจำกัดความสำหรับดัชนีเอกสารและการจัดเก็บ |
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
ปณิธาน | ตัวเลข | ตั้งค่าความละเอียดในการให้คะแนนสำหรับบริบท (ค่าเริ่มต้น: 1) | 1 |
ความลึก | เท็จ ตัวเลข | เปิด/ปิดใช้งานการจัดทำดัชนีตามบริบทและยังกำหนดระยะห่างตามบริบทของความเกี่ยวข้องอีกด้วย ความลึกคือจำนวนคำ/โทเค็นสูงสุดที่พิจารณาว่าเกี่ยวข้อง | 1 |
แบบสองทิศทาง | บูลีน | ตั้งค่าผลการค้นหาแบบสองทิศทาง หากเปิดใช้งานและข้อความต้นฉบับมี "หมวกสีแดง" จะพบข้อความค้นหา "หมวกสีแดง" และ "หมวกสีแดง" | จริง |
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
รหัส | สตริง | "ไอดี"" | |
แท็ก | เท็จ สตริง | "แท็ก" | |
ดัชนี | สตริง อาร์เรย์<สตริง> อาร์เรย์<วัตถุ> | ||
เก็บ | บูลีน สตริง อาร์เรย์<สตริง> | เท็จ |
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
แยก | เท็จ RegExp สตริง | กฎการแยกคำเมื่อใช้โทเค็นไนเซอร์ที่ไม่ได้กำหนดเอง (ในตัว เช่น "ส่งต่อ") ใช้สตริง/ถ่านหรือใช้นิพจน์ทั่วไป (ค่าเริ่มต้น: /W+/ ) | /[W_]+/ |
rtl | บูลีน | เปิดใช้งานการเข้ารหัสจากขวาไปซ้าย | เท็จ |
เข้ารหัส | ฟังก์ชั่น (str) => [คำ] | ฟังก์ชั่นการเข้ารหัสแบบกำหนดเอง | /lang/latin/default.js |
ตัวเลือก | ค่านิยม | คำอธิบาย |
ลำต้น | เท็จ สตริง การทำงาน | ปิดใช้งานหรือส่งผ่านธงชวเลขภาษา (ISO-3166) หรือวัตถุที่กำหนดเอง |
กรอง | เท็จ สตริง การทำงาน | ปิดใช้งานหรือส่งผ่านแฟล็กชวเลขภาษา (ISO-3166) หรืออาร์เรย์ที่กำหนดเอง |
เครื่องจับคู่ | เท็จ สตริง การทำงาน | ปิดใช้งานหรือส่งผ่านแฟล็กชวเลขภาษา (ISO-3166) หรืออาร์เรย์ที่กำหนดเอง |
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
ขีด จำกัด | ตัวเลข | กำหนดขีดจำกัดของผลลัพธ์ | 100 |
ชดเชย | ตัวเลข | ใช้ออฟเซ็ต (ข้ามรายการ) | 0 |
แนะนำ | บูลีน | เปิดใช้งานคำแนะนำในผลลัพธ์ | เท็จ |
ตัวเลือก | ค่านิยม | คำอธิบาย | ค่าเริ่มต้น |
ดัชนี | สตริง อาร์เรย์<สตริง> อาร์เรย์<วัตถุ> | ตั้งค่าฟิลด์เอกสารที่ควรค้นหา เมื่อไม่ได้ตั้งค่าฟิลด์ใดๆ ฟิลด์ทั้งหมดจะถูกค้นหา นอกจากนี้ยังรองรับตัวเลือกแบบกำหนดเองต่อฟิลด์ด้วย | |
แท็ก | สตริง อาร์เรย์<สตริง> | ตั้งค่าฟิลด์เอกสารที่ควรค้นหา เมื่อไม่ได้ตั้งค่าฟิลด์ใดๆ ฟิลด์ทั้งหมดจะถูกค้นหา นอกจากนี้ยังรองรับตัวเลือกแบบกำหนดเองต่อฟิลด์ด้วย | เท็จ |
เสริมสร้าง | บูลีน | เพิ่ม ID จากผลลัพธ์ด้วยเอกสารที่เกี่ยวข้อง | เท็จ |
บูล | "และ" "หรือ" | ตั้งค่าตัวดำเนินการเชิงตรรกะที่ใช้เมื่อค้นหาผ่านหลายฟิลด์หรือแท็ก | "หรือ" |
Tokenizer ส่งผลต่อหน่วยความจำที่ต้องการรวมถึงเวลาในการสืบค้นและความยืดหยุ่นของการจับคู่บางส่วน ลองเลือกโทเค็นไนเซอร์ตัวบนสุดที่เหมาะกับความต้องการของคุณ:
ตัวเลือก | คำอธิบาย | ตัวอย่าง | ปัจจัยด้านความจำ (n = ความยาวของคำ) |
"เข้มงวด" | ดัชนีคำทั้งหมด | foobar | * 1 |
"ซึ่งไปข้างหน้า" | ดัชนีคำทีละน้อยในทิศทางไปข้างหน้า | fo โอบาร์foob ร์ | * n |
"ย้อนกลับ" | ดัชนีคำที่เพิ่มขึ้นทั้งสองทิศทาง | ฟูบ อา ar สำหรับ obar | * 2น - 1 |
"เต็ม" | จัดทำดัชนีทุกชุดค่าผสมที่เป็นไปได้ | สำหรับ oba อาร์ฉ oob อาร์ | * น * (น - 1) |
การเข้ารหัสส่งผลต่อหน่วยความจำที่ต้องการรวมถึงเวลาสืบค้นและการจับคู่การออกเสียงด้วย ลองเลือกตัวเข้ารหัสด้านบนสุดที่เหมาะกับความต้องการของคุณ หรือส่งผ่านตัวเข้ารหัสแบบกำหนดเอง:
ตัวเลือก | คำอธิบาย | ผลบวกลวง | การบีบอัด |
เท็จ | ปิดการเข้ารหัส | เลขที่ | 0% |
"ค่าเริ่มต้น" | การเข้ารหัสแบบคำนึงถึงขนาดตัวพิมพ์ | เลขที่ | 0% |
"เรียบง่าย" | การเข้ารหัสแบบคำนึงถึงขนาดตัวพิมพ์ การทำให้เป็นมาตรฐานของชุดอักขระ | เลขที่ | ~ 3% |
"สมดุล" | การเข้ารหัสแบบคำนึงถึงขนาดตัวพิมพ์ การทำให้เป็นมาตรฐานของชุดอักขระ การเปลี่ยนแปลงตามตัวอักษร | เลขที่ | ~ 30% |
"ขั้นสูง" | การเข้ารหัสแบบคำนึงถึงขนาดตัวพิมพ์ การทำให้เป็นมาตรฐานของชุดอักขระ การเปลี่ยนแปลงตามตัวอักษร การทำให้เป็นมาตรฐานการออกเสียง | เลขที่ | ~ 40% |
"พิเศษ" | การเข้ารหัสแบบคำนึงถึงขนาดตัวพิมพ์ การทำให้เป็นมาตรฐานของชุดอักขระ การเปลี่ยนแปลงตามตัวอักษร การทำให้เป็นมาตรฐานการออกเสียง การแปลงซาวด์เด็กซ์ | ใช่ | ~ 65% |
การทำงาน() | ส่งการเข้ารหัสที่กำหนดเองผ่าน ฟังก์ชัน (สตริง): [คำ] |
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 (แนะนำให้ใช้ค่าจากประเภท number
) รหัสเหล่านี้เป็นข้อมูลอ้างอิงที่ไม่ซ้ำกันสำหรับเนื้อหาที่กำหนด นี่เป็นสิ่งสำคัญเมื่อคุณอัปเดตหรือเพิ่มเนื้อหาผ่านรหัสที่มีอยู่ เมื่อการอ้างอิงไม่ใช่ปัญหา คุณสามารถใช้สิ่งง่ายๆ เช่น 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" ) ;
}
คุณสามารถเรียกแต่ละวิธีในเวอร์ชัน async ได้ เช่น 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)
โปรดทราบว่า index.add(id, content)
จะดำเนินการ "อัปเดต" ภายใต้ประทุนเมื่อมีการสร้างดัชนี id แล้ว
เนื้อหาที่ต่อท้ายจะมีบริบทของตัวเองและยังมี 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")
คุณจะได้รับรหัสดัชนี 1 เป็นรายการแรกในผลลัพธ์ เนื่องจากบริบทเริ่มต้นจากศูนย์สำหรับข้อมูลที่ต่อท้าย (ไม่ซ้อนกันกับบริบทเก่า) และที่นี่ "ดัชนี " คือเทอมแรก
หากคุณไม่ต้องการให้มีพฤติกรรมเช่นนี้ เพียงแค่ใช้ index.add(id, content)
และระบุเนื้อหาแบบเต็ม
ดัชนี. อัปเดต (id, สตริง)
index . update ( 0 , "Max Miller" ) ;
ดัชนี. ลบ(รหัส)
index . remove ( 0 ) ;
Tokenizer แบ่งคำ/คำศัพท์ออกเป็นส่วนประกอบหรือบางส่วน
กำหนดโทเค็นไนเซอร์แบบกำหนดเองส่วนตัวระหว่างการสร้าง/การเริ่มต้น:
var index = new FlexSearch ( {
tokenize : function ( str ) {
return str . split ( / s-/ / g ) ;
}
} ) ;
ฟังก์ชัน tokenizer รับสตริงเป็นพารามิเตอร์ และต้องส่งคืนอาร์เรย์ของสตริงที่แสดงถึงคำหรือคำศัพท์ ในบางภาษา ตัวอักษรทุกตัวถือเป็นคำศัพท์และไม่ได้คั่นด้วยช่องว่าง
Stemmer: การกลายพันธุ์ทางภาษาหลายอย่างของคำเดียวกัน (เช่น "run" และ "running")
ตัวกรอง: บัญชีดำของคำที่จะกรองออกจากการจัดทำดัชนีเลย (เช่น "และ", "ถึง" หรือ "เป็น")
กำหนดก้านหรือตัวกรองแบบกำหนดเองส่วนตัวระหว่างการสร้าง/การเริ่มต้น:
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 ;
}
} ) ;
หรือกำหนดภาษาต้นกำเนิด/ตัวกรองทั่วโลก:
Stemmer จะถูกส่งผ่านเป็นวัตถุ (คู่คีย์-ค่า) กรองเป็นอาร์เรย์
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 >
...
ตอนนี้คุณสามารถกำหนด Stemmer ในตัวระหว่างการสร้าง/การเริ่มต้นได้:
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" ให้เป็น จริง และใช้โทเค็นไนเซอร์ที่เข้ากันได้:
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
จึงกลายเป็นสมาชิกหลักของตัวเลือก
สำหรับไวยากรณ์ใหม่ ฟิลด์ "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 ) ;
เมื่อทราบรหัสแล้ว คุณสามารถลบออกได้โดย (เร็วกว่า):
index . remove ( id ) ;
ในตัวอย่างที่ซับซ้อนด้านบน keywords
ของฟิลด์เป็นอาร์เรย์ แต่มาร์กอัปในที่นี้ไม่มีวงเล็บเหมือน keywords[]
ซึ่งจะตรวจจับอาร์เรย์ด้วย แต่แทนที่จะผนวกแต่ละรายการเข้ากับบริบทใหม่ อาร์เรย์จะถูกรวมเข้ากับสตริงขนาดใหญ่และเพิ่มลงในดัชนี
ความแตกต่างของการเพิ่มเนื้อหาอาเรย์ทั้งสองประเภทคือความเกี่ยวข้องเมื่อทำการค้นหา เมื่อเพิ่มแต่ละรายการของอาร์เรย์ผ่าน append()
เข้ากับบริบทของตัวเองโดยใช้ field[]
ดังนั้นความเกี่ยวข้องของรายการสุดท้ายจะพร้อมกันกับรายการแรก เมื่อคุณปล่อยวงเล็บไว้ในสัญลักษณ์ มันจะรวมอาร์เรย์เข้ากับสตริงที่คั่นด้วยช่องว่างหนึ่งสตริง ที่นี่รายการแรกมีความเกี่ยวข้องสูงสุด ในขณะที่รายการสุดท้ายมีความเกี่ยวข้องต่ำที่สุด
ดังนั้น สมมติว่าคำหลักจากตัวอย่างด้านบนได้รับการจัดเรียงไว้ล่วงหน้าตามความเกี่ยวข้องกับความนิยม คุณจึงต้องการรักษาลำดับนี้ไว้ (ข้อมูลความเกี่ยวข้อง) เพื่อจุดประสงค์นี้ อย่าเพิ่มวงเล็บให้กับสัญกรณ์ มิฉะนั้น จะใช้รายการในบริบทการให้คะแนนใหม่ (ลำดับเก่ากำลังสูญหาย)
นอกจากนี้ คุณยังสามารถใช้เครื่องหมายวงเล็บเหลี่ยมเพื่อประสิทธิภาพที่ดีขึ้นและขนาดหน่วยความจำที่เล็กลงได้ ใช้เมื่อคุณไม่ต้องการรายละเอียดความเกี่ยวข้องของรายการ
ค้นหาในทุกช่อง:
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"
} ) ;
คุณจะได้รับผลลัพธ์ที่มีการสืบค้นในทั้งสองฟิลด์ แค่นั้นแหละ.
เช่นเดียวกับ key
สำหรับ ID เพียงกำหนดเส้นทางไปยังแท็ก:
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"
} ) ;
คุณจะได้รับผลลัพธ์ที่มีทั้งสองแท็ก (ในตัวอย่างนี้มีเพียงระเบียนเดียวที่มีแท็ก "dog" และ "animal")
คุณยังสามารถดึงผลลัพธ์จากแท็กตั้งแต่หนึ่งแท็กขึ้นไปเมื่อไม่มีการส่งข้อความค้นหา:
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]" ,
}
} ]
} ]
ทั้งฟิลด์ "ผู้เขียน" และ "อีเมล" จะไม่ถูกจัดทำดัชนี
เพียงเชื่อมโยงวิธีการเช่น:
var index = FlexSearch . create ( )
. addMatcher ( { 'â' : 'a' } )
. add ( 0 , 'foo' )
. add ( 1 , 'bar' ) ;
index . remove ( 0 ) . update ( 1 , 'foo' ) . add ( 2 , 'foobar' ) ;
หมายเหตุ: คุณลักษณะนี้ถูกปิดใช้งานตามค่าเริ่มต้นเนื่องจากมีการใช้หน่วยความจำเพิ่มเติม อ่านข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเปิดใช้งานได้ที่นี่
FlexSearch แนะนำกลไกการให้คะแนนใหม่ที่เรียกว่า Contextual Search ซึ่งคิดค้นโดย 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 เท่า (เนื่องจากบาลานเซอร์ไม่จำเป็นต้องทำงาน)
โมเดลผู้ปฏิบัติงานใหม่จากเวอร์ชัน 0.7.0 แบ่งออกเป็น "ฟิลด์" จากเอกสาร (ผู้ปฏิบัติงาน 1 คน = ดัชนีฟิลด์ 1 รายการ) วิธีนี้ทำให้ผู้ปฏิบัติงานสามารถแก้ไขงาน (งานย่อย) ได้อย่างสมบูรณ์ ข้อเสียของกระบวนทัศน์นี้คือการจัดเก็บเนื้อหาอาจไม่สมดุลอย่างสมบูรณ์ (ช่องอาจมีเนื้อหาที่มีความยาวต่างกัน) ในทางกลับกัน ไม่มีข้อบ่งชี้ว่าการปรับสมดุลพื้นที่จัดเก็บข้อมูลจะให้ข้อได้เปรียบใดๆ (ทั้งหมดต้องใช้ปริมาณรวมเท่ากัน)
เมื่อใช้ดัชนีเอกสารให้ใช้ตัวเลือก "ผู้ปฏิบัติงาน":
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
ของวิธีการทั้งหมดเท่านั้น นั่นหมายความว่าเมื่อคุณเรียกindex.search()
บน WorkerIndex สิ่งนี้จะทำงานในแบบ async เช่นเดียวกับที่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 ) ;
ภายใน 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
เพื่อรักษาพื้นที่หน่วยความจำเหลือน้อยในระหว่างกระบวนการที่ยาวนาน
การส่งออกมีการเปลี่ยนแปลงเล็กน้อย ปัจจุบันการส่งออกประกอบด้วยชิ้นส่วนเล็กๆ หลายชิ้น แทนที่จะเป็นสินค้าขนาดใหญ่เพียงชิ้นเดียว คุณต้องส่งฟังก์ชันโทรกลับซึ่งมี 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 เป็นหลักหรือเพื่อจัดเก็บดัชนีที่คุณต้องการมอบหมายจากเซิร์ฟเวอร์ไปยังไคลเอนต์
ขนาดของการส่งออกสอดคล้องกับการใช้หน่วยความจำของไลบรารี ในการลดขนาดการส่งออก คุณต้องใช้การกำหนดค่าที่มีพื้นที่หน่วยความจำน้อยกว่า (ใช้ตารางที่ด้านล่างเพื่อรับข้อมูลเกี่ยวกับการกำหนดค่าและการจัดสรรหน่วยความจำ)
เมื่อรูทีนการบันทึกของคุณทำงานแบบอะซิงโครนัส คุณจะต้องส่งคืนสัญญา:
index . export ( function ( key , data ) {
return new Promise ( function ( resolve ) {
// do the saving as async
resolve ( ) ;
} ) ;
} ) ;
คุณไม่สามารถส่งออกตารางเพิ่มเติมสำหรับคุณลักษณะ "fastupdate" ตารางเหล่านี้มีการอ้างอิง และเมื่อเก็บไว้ ตารางเหล่านี้จะถูกทำให้เป็นอนุกรมอย่างสมบูรณ์และมีขนาดใหญ่เกินไป lib จะจัดการสิ่งเหล่านี้ให้คุณโดยอัตโนมัติ เมื่อนำเข้าข้อมูล ดัชนีจะปิดใช้งาน "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
schema เป็นค่าเริ่มต้น
สนาม | หมวดหมู่ | คำอธิบาย |
เข้ารหัส | ชุดอักขระ | ฟังก์ชันตัวเข้ารหัส ต้องส่งคืนอาร์เรย์ของคำที่แยกจากกัน (หรือสตริงว่าง) |
rtl | ชุดอักขระ | คุณสมบัติบูลีนซึ่งระบุการเข้ารหัสจากขวาไปซ้าย |
กรอง | ภาษา | ตัวกรองเรียกอีกอย่างว่า "คำหยุด" ซึ่งจะกรองคำไม่ให้ถูกจัดทำดัชนีโดยสมบูรณ์ |
ลำต้น | ภาษา | Stemmer จะลบคำลงท้ายออกและเป็น "การทำให้เป็นมาตรฐานบางส่วน" คำที่ลงท้ายจะตรงกันเมื่อความยาวของคำมากกว่าส่วนที่ตรงกัน |
เครื่องจับคู่ | ภาษา | 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 >
เมื่อใช้เวอร์ชัน "Bundle" เต็มรูปแบบตัวเข้ารหัสละตินในตัวจะรวมอยู่แล้วและคุณต้องโหลดไฟล์ภาษา:
< 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 >
เมื่อใช้เวอร์ชัน "Bundle" เต็มรูปแบบตัวเข้ารหัสละตินในตัวจะรวมอยู่แล้วและคุณต้องโหลดไฟล์ภาษา:
< 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 คุณไม่สามารถให้ tokenizer บางส่วนของคุณเองได้เนื่องจากเป็นการพึ่งพาโดยตรงกับหน่วยหลัก tokenizer ในตัวของ FlexSearch จะแยกแต่ละคำออกเป็นชิ้นส่วนตามรูปแบบที่แตกต่างกัน:
นี่คือไปป์ไลน์เริ่มต้นที่จัดทำโดย FlexSearch:
ในตอนแรกลองดูไปป์ไลน์เริ่มต้นใน src/common.js
มันง่ายมากและตรงไปตรงมา ไปป์ไลน์จะดำเนินการเป็นแบบผกผันของการควบคุมการใช้งานการเข้ารหัสขั้นสุดท้ายจะต้องจัดการกับชุดถ่านและการแปลงเฉพาะภาษา วิธีแก้ปัญหานี้ได้ทิ้งจากการทดสอบจำนวนมาก
ฉีดท่อเริ่มต้นด้วยเช่น:
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/
หากมีอยู่คุณสามารถขยายหรือให้ตัวแปร (เช่นภาษาถิ่น/สแลง) หากภาษาไม่มีอยู่ให้สร้างไฟล์ใหม่และตรวจสอบว่ามีชุดตัวอักษรที่มีอยู่ (เช่นละติน) ใด ๆ ที่เหมาะสมกับภาษาของคุณหรือไม่ เมื่อไม่มีชุดถ่านคุณจะต้องจัดเตรียมชุดถ่านเป็นฐานสำหรับภาษา
ชุดใหม่ควรให้อย่างน้อย:
encode
ฟังก์ชั่นที่ทำให้ charset ของเนื้อหาข้อความที่ผ่านเป็นปกติ (ลบตัวอักษรพิเศษการแปลงภาษา ฯลฯ ) และ ส่งคืนอาร์เรย์ของคำที่แยกออกมา นอกจากนี้ยังต้องใช้ตัวกรอง Stemmer, matcher หรือ stopword ที่นี่ เมื่อภาษาไม่มีคำพูดให้แน่ใจว่าให้สิ่งที่คล้ายกันเช่นสัญญาณภาษาจีนแต่ละอันอาจเป็น "คำ" อย่าส่งคืนเนื้อหาข้อความทั้งหมดโดยไม่แยกrtl
ธงบูลีนซึ่งบ่งบอกถึงการเข้ารหัสทางซ้ายไปซ้ายโดยพื้นฐานแล้วความต้องการของ Charset เพียงเพื่อให้ฟังก์ชั่น encoder พร้อมกับตัวบ่งชี้สำหรับการเข้ารหัสขวาไปซ้าย:
export function encode ( str ) { return [ str ] }
export const rtl = false ;
สตริงอ้างอิง: "Björn-Phillipp Mayer"
แบบสอบถาม | ค่าเริ่มต้น | เรียบง่าย | ขั้นสูง | พิเศษ |
Björn | ใช่ | ใช่ | ใช่ | ใช่ |
Björ | ใช่ | ใช่ | ใช่ | ใช่ |
บียอร์น | เลขที่ | ใช่ | ใช่ | ใช่ |
bjoern | เลขที่ | เลขที่ | ใช่ | ใช่ |
ชาวฟิลิปป์ | เลขที่ | เลขที่ | ใช่ | ใช่ |
ชาวฟิลิปปินส์ | เลขที่ | เลขที่ | ใช่ | ใช่ |
björnphillip | เลขที่ | ใช่ | ใช่ | ใช่ |
ไมเออร์ | เลขที่ | เลขที่ | ใช่ | ใช่ |
Björn Meier | เลขที่ | เลขที่ | ใช่ | ใช่ |
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
} ) ;
หนังสือ "Gulliver's Travels" (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 |
ความยาวของ minlength | -2 (ต่อระดับ) | +2 (ต่อระดับ) | -3 (ต่อระดับ) | +2 (ต่อระดับ) |
แบบสองทิศทาง | -2 | 0 | +3 | -1 |
fastupdate | +1 | +10 (อัปเดตลบ) | 0 | 0 |
ปรับให้เหมาะสม: จริง | -7 | -1 | 0 | -3 |
encoder: "icase" | 0 | 0 | 0 | 0 |
เข้ารหัส: "ง่าย" | -2 | -1 | +2 | 0 |
encoder: "Advanced" | -3 | -2 | +4 | 0 |
encoder: "Extra" | -5 | -5 | +6 | 0 |
encoder: "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 ที่ผ่านมามีผลต่อการใช้หน่วยความจำอย่างมีนัยสำคัญ หากเป็นไปไม่ได้คุณควรพิจารณาใช้ตารางดัชนีและแมปรหัสด้วยดัชนีสิ่งนี้จะกลายเป็นสิ่งสำคัญโดยเฉพาะอย่างยิ่งเมื่อใช้ดัชนีบริบทกับเนื้อหาจำนวนมาก
เมื่อใดก็ตามที่คุณทำได้ลองแบ่งเนื้อหาตามหมวดหมู่และเพิ่มลงในดัชนีของตัวเองเช่น:
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