곧 출시될 FlexSearch v0.8에 대해 논의해 보겠습니다. #415
기본 시작 • API 참조 • 문서 색인 • 작업자 사용 • 변경 로그
이 프로젝트를 계속 유지하고 귀하의 요구 사항을 해결하는 데 모든 기여를 제공하기 위해 개인적인 기부를 통해 저를 도울 수 있습니다.
안티테제 운영 LLC
원시 검색 속도 측면에서 FlexSearch는 모든 단일 검색 라이브러리보다 성능이 뛰어나며 다중 필드 검색, 음성 변환 또는 부분 일치와 같은 유연한 검색 기능도 제공합니다.
사용된 옵션에 따라 가장 메모리 효율적인 인덱스도 제공합니다. FlexSearch는 실제로 다른 라이브러리에 비해 최대 1,000,000배 빠르게 쿼리를 수행하는 사전 점수가 매겨진 어휘 사전 아키텍처를 기반으로 하는 "컨텍스트 인덱스"라는 새로운 점수 알고리즘을 도입합니다. FlexSearch는 또한 균형 잡힌 전용 스레드를 통해 인덱스에 대한 업데이트나 쿼리를 병렬로 수행할 수 있는 웹 작업자뿐만 아니라 비차단 비동기 처리 모델도 제공합니다.
지원되는 플랫폼:
도서관 비교 "걸리버 여행기":
플러그인(외부 프로젝트):
짓다 | 파일 | 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 지원을 위한 폴리필이 포함되어 있습니다.
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.8kb | 5.3kb | 2.9kb |
비교 실행: 성능 벤치마크 "걸리버 여행기"
초당 작업은 높을수록 좋습니다. 단, "메모리" 테스트에서는 낮을수록 좋습니다.
계급 | 도서관 | 메모리 | 쿼리(단일 용어) | 쿼리(다중 용어) | 쿼리(장문) | 쿼리(중복) | 쿼리(찾을 수 없음) |
1 | FlexSearch | 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-콘텐츠 쌍을 저장하지만 백그라운드에서 전용 작업자 스레드로 실행되는 플랫 인덱스이기도 합니다.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 >
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 Index처럼 작동합니다. 문서의 작업자 지원은 생성 중에 { worker: true }
적절한 옵션을 전달하여 활성화해야 합니다.
Worker
인덱스에서 호출되는 모든 메서드는 비동기로 처리됩니다.Promise
를 돌려받거나 마지막 매개변수로 콜백 함수를 제공할 수도 있습니다.
전역 방법:
색인 방법:
WorkerIndex 메소드:
문서 방법:
* 이러한 각 메서드에는 비동기식 상응하는 메서드가 있습니다.
비동기 버전:
비동기 메소드는 Promise
를 반환합니다. 또는 콜백 함수를 마지막 매개변수로 전달할 수도 있습니다.
메서드 export
및 import
는 작업자 기반 인덱스에서 호출하는 모든 메서드와 마찬가지로 항상 비동기식입니다.
FlexSearch는 고도로 사용자 정의가 가능합니다. 올바른 옵션을 사용하면 결과는 물론 메모리 경제 및 쿼리 시간도 향상될 수 있습니다.
옵션 | 가치 | 설명 | 기본 |
사전 설정 | "메모리" "성능" "성냥" "점수" "기본" | 바로가기 또는 사용자 정의 설정의 기반으로 사용되는 구성 프로필입니다. | "기본" |
토큰화하다 | "엄격한" "앞으로" "뒤집다" "가득한" | 인덱싱 모드(토크나이저). 내장된 기능 중 하나를 선택하거나 사용자 정의 토크나이저 기능을 전달하세요. | "엄격한" |
은닉처 | 부울 숫자 | 캐시된 항목의 용량을 활성화/비활성화 및/또는 설정합니다. 숫자를 제한으로 전달하면 캐시는 인기도에 따라 저장된 항목의 균형을 자동으로 조정합니다 . 참고: "true"를 사용하면 캐시에 제한이 없고 성장이 무제한입니다. | 거짓 |
해결 | 숫자 | 채점 해상도를 설정합니다(기본값: 9). | 9 |
문맥 | 부울 컨텍스트 옵션 | 상황별 인덱싱을 활성화/비활성화합니다. "true"를 값으로 전달하면 컨텍스트에 대한 기본값이 사용됩니다. | 거짓 |
최적화하다 | 부울 | 활성화되면 인덱스에 대해 메모리 최적화 스택 흐름을 사용합니다. | 진실 |
후원 | 함수(arr, str, int) => 부동 소수점 | 콘텐츠를 인덱스로 인덱싱할 때 사용되는 사용자 정의 부스트 함수입니다. 함수에는 다음과 같은 서명이 있습니다: Function(words[], term, index) => Float . 여기에는 모든 단어의 배열, 현재 용어 및 해당 용어가 단어 배열에 배치된 현재 인덱스를 얻는 3개의 매개변수가 있습니다. 예를 들어 용어 발생과 같은 자체 계산을 적용하고 이 요소를 반환할 수 있습니다(<1은 관련성이 낮아지는 것을 의미하고 >1은 관련성이 증가함을 의미).참고: 이 기능은 현재 토크나이저 "엄격"만을 사용하여 제한됩니다. | null |
언어별 옵션 및 인코딩: | |||
문자셋 | 문자셋 페이로드 문자열(키) | 사용자 정의 문자 세트 페이로드를 제공하거나 내장 문자 세트의 키 중 하나를 전달하십시오. | "라틴어" |
언어 | 언어 페이로드 문자열(키) | 사용자 정의 언어 페이로드를 제공하거나 내장 언어의 언어 단축 플래그(ISO-3166)를 전달합니다. | null |
인코딩하다 | 거짓 "기본" "단순한" "균형" "고급의" "추가의" function(str) => [단어] | 인코딩 유형입니다. 내장된 기능 중 하나를 선택하거나 사용자 정의 인코딩 기능을 전달하세요. | "기본" |
형태소 분석기 | 거짓 끈 기능 | 거짓 | |
필터 | 거짓 끈 기능 | 거짓 | |
매처 | 거짓 끈 기능 | 거짓 | |
문서 색인에 대한 추가 옵션: | |||
노동자 | 부울 | 실행 중인 작업자 스레드 수를 활성화/비활성화하고 설정합니다. | 거짓 |
문서 | 문서 설명자 | 문서 인덱스 및 저장소에 대한 정의를 포함합니다. |
옵션 | 가치 | 설명 | 기본 |
해결 | 숫자 | 컨텍스트에 대한 점수 결정을 설정합니다(기본값: 1). | 1 |
깊이 | 거짓 숫자 | 상황별 인덱싱을 활성화/비활성화하고 상황별 관련성 거리도 설정합니다. 깊이는 관련성이 있는 것으로 간주되는 용어의 최대 단어/토큰 수입니다. | 1 |
양방향 | 부울 | 양방향 검색 결과를 설정합니다. 활성화되어 있고 소스 텍스트에 "red hat"이 포함되어 있으면 "red hat" 및 "hat red" 쿼리에 대해 검색됩니다. | 진실 |
옵션 | 가치 | 설명 | 기본 |
ID | 끈 | "ID"" | |
꼬리표 | 거짓 끈 | "꼬리표" | |
색인 | 끈 배열<문자열> 배열<객체> | ||
가게 | 부울 끈 배열<문자열> | 거짓 |
옵션 | 가치 | 설명 | 기본 |
나뉘다 | 거짓 정규식 끈 | 사용자 지정되지 않은 토크나이저(내장됨, 예: "forward")를 사용할 때 단어를 분할하는 규칙입니다. 문자열/문자를 사용하거나 정규식을 사용하십시오(기본값: /W+/ ). | /[W_]+/ |
rtl | 부울 | 오른쪽에서 왼쪽으로 인코딩을 활성화합니다. | 거짓 |
인코딩하다 | function(str) => [단어] | 사용자 정의 인코딩 기능. | /lang/latin/default.js |
옵션 | 가치 | 설명 |
형태소 분석기 | 거짓 끈 기능 | 언어 속기 플래그(ISO-3166) 또는 사용자 정의 개체를 비활성화하거나 전달합니다. |
필터 | 거짓 끈 기능 | 언어 속기 플래그(ISO-3166) 또는 사용자 정의 배열을 비활성화하거나 전달합니다. |
매처 | 거짓 끈 기능 | 언어 속기 플래그(ISO-3166) 또는 사용자 정의 배열을 비활성화하거나 전달합니다. |
옵션 | 가치 | 설명 | 기본 |
한계 | 숫자 | 결과의 한계를 설정합니다. | 100 |
오프셋 | 숫자 | 오프셋을 적용합니다(항목 건너뛰기). | 0 |
제안하다 | 부울 | 결과에서 제안을 활성화합니다. | 거짓 |
옵션 | 가치 | 설명 | 기본 |
색인 | 끈 배열<문자열> 배열<객체> | 검색할 문서 필드를 설정합니다. 필드를 설정하지 않으면 모든 필드가 검색됩니다. 필드별 사용자 정의 옵션도 지원됩니다. | |
꼬리표 | 끈 배열<문자열> | 검색할 문서 필드를 설정합니다. 필드를 설정하지 않으면 모든 필드가 검색됩니다. 필드별 사용자 정의 옵션도 지원됩니다. | 거짓 |
높이다 | 부울 | 해당 문서로 결과의 ID를 강화합니다. | 거짓 |
부울 | "그리고" "또는" | 여러 필드 또는 태그를 통해 검색할 때 사용되는 논리 연산자를 설정합니다. | "또는" |
토크나이저는 쿼리 시간과 부분 일치의 유연성으로도 필요한 메모리에 영향을 줍니다. 귀하의 필요에 맞는 가장 높은 토크나이저를 선택해 보십시오:
옵션 | 설명 | 예 | 메모리 팩터(n = 단어 길이) |
"엄격한" | 전체 단어 색인 | foobar | * 1 |
"앞으로" | 단어를 순방향으로 점진적으로 색인화 | fo 오바르foob ar | * N |
"뒤집다" | 단어를 양방향으로 점진적으로 색인화 | foob 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++
와 같은 간단한 것을 사용할 수 있습니다.
색인. 추가(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)
수행할 때처럼 이전에 색인화된 내용을 덮어쓰지 않습니다. 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")
쿼리하면 추가된 데이터에 대해 컨텍스트가 0부터 시작하고(이전 컨텍스트에 쌓이지 않음) 여기에 "index"가 있기 때문에 index.search("index")를 결과의 첫 번째 항목으로 인덱스 ID 1을 얻게 됩니다. "가 첫 번째 용어입니다.
이 동작을 원하지 않으면 표준 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 ) ;
}
} ) ;
토크나이저 함수는 문자열을 매개변수로 가져오고 단어나 용어를 나타내는 문자열 배열을 반환해야 합니다. 일부 언어에서는 모든 문자가 용어이며 공백으로 구분되지 않습니다.
형태소 분석기: 동일한 단어의 여러 언어적 변형(예: "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
옵션의 주요 구성원이 됩니다.
새 구문에서는 "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
}
} ]
}
} ) ;
참고: "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
} ] ) ;
동일한 필드를 통해 다른 쿼리로 검색을 수행할 수 있습니다.
필드별 옵션을 전달할 때 각 필드에 대한 전체 구성을 제공해야 합니다. 문서 설명자처럼 상속되지 않습니다.
문서에 대해 다음 두 가지 규칙을 따라야 합니다.
[ // <-- 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 }}
첫 번째 인덱스는 쿼리가 적용된 필드의 배열입니다. 이 필드 각각에는 "필드"와 "결과"라는 두 가지 속성을 가진 레코드(객체)가 있습니다. "결과"도 배열이며 이 특정 필드에 대한 결과를 포함합니다. 결과는 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 */ } }
]
} ]
"field" 대신 pluck
사용하면 명시적으로 하나의 필드만 선택하고 평면 표현을 얻을 수 있습니다.
index . search ( query , { pluck : "title" , enrich : true } ) ;
[
{ id : 0 , doc : { /* document */ } } ,
{ id : 1 , doc : { /* document */ } } ,
{ id : 2 , doc : { /* document */ } }
]
이 결과 집합은 "부울 검색"을 대체합니다. 중첩된 개체에 부울 논리를 적용하는 대신 결과 집합 위에 직접 논리를 동적으로 적용할 수 있습니다. 이는 결과를 처리하는 방법에 대한 엄청난 가능성을 열어줍니다. 따라서 필드의 결과가 더 이상 하나의 결과로 압축되지 않습니다. 이는 필드 이름 및 더 이상 혼합되지 않은 각 필드 결과의 관련성과 같은 일부 중요한 정보를 유지합니다.
필드 검색은 기본적으로 부울 "또는" 논리를 사용하여 쿼리를 적용합니다. 각 필드에는 지정된 쿼리에 대한 자체 결과가 있습니다.
bool
속성이 여전히 지원되는 상황이 있습니다. 필드 검색의 기본 "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" ]
} ) ;
그러면 주어진 태그 중 하나로 태그가 지정된 결과가 제공됩니다.
기본적으로 여러 태그가 부울 "또는"으로 적용됩니다. 태그 중 하나만 존재하면 됩니다.
이는 bool
속성이 여전히 지원되는 또 다른 상황입니다. 태그 검색에서 기본 "or" 논리를 "and"로 전환하려는 경우, 예:
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는 이 라이브러리의 저자인 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를 직접 생성할 수도 있습니다( 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 ) ;
또는 모든 요청이 완료되었을 때 콜백이 하나만 있는 경우 "모든 작업 완료"의 우선순위를 지정하는 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
와 함께 비동기 버전을 사용하여 긴 프로세스 중에 낮은 메모리 공간을 유지하는 것이 좋습니다.
내보내기가 약간 변경되었습니다. 이제 수출품은 하나의 큰 벌크가 아닌 여러 개의 작은 부품으로 구성됩니다. 2개의 인수 "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" 기능을 위해 추가 테이블을 내보낼 수 없습니다. 이 테이블에는 참조가 존재하며 저장되면 완전히 직렬화되어 너무 커집니다. 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
스키마가 사용됩니다.
필드 | 범주 | 설명 |
인코딩하다 | 문자셋 | 인코더 기능. 분리된 단어의 배열(또는 빈 문자열)을 반환해야 합니다. |
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 >
전체 "번들" 버전을 사용하는 경우 내장 라틴어 인코더가 이미 포함되어 있으므로 언어 파일만 로드하면 됩니다.
< 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: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
(특수 숯 제거, 설측 변환 등) 분리 된 단어 배열을 반환합니다 . 또한 여기에 Stemmer, Matcher 또는 Stopword 필터를 적용해야합니다. 언어에 단어가 없으면 비슷한 것을 제공해야합니다. 예를 들어 각 중국의 표시는 "단어"가 될 수 있습니다. 분할없이 전체 텍스트 콘텐츠를 반환하지 마십시오.rtl
오른쪽에서 왼쪽으로 인코딩을 나타내는 부울 플래그기본적으로 Charset은 오른쪽에서 왼쪽으로 인코딩을위한 표시기와 함께 인코더 기능을 제공하기 만하면됩니다.
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 | 아니요 | 아니요 | 예 | 예 |
합성기 Mair | 아니요 | 아니요 | 아니요 | 예 |
(거짓 긍정) | 아니요 | 아니요 | 아니요 | 예 |
"Gulliver 's Travels Swift Jonathan 1726"이라는 책은 아래 예제에 대해 완전히 색인화되었습니다.
가장 메모리에 최적화 된 의미있는 설정은 인덱스 된 전체 책에 대해 1.2MB 만 할당됩니다! 이것은 아마도 검색 라이브러리에서 얻을 수있는 가장 작은 메모리 풋 프린트 일 것입니다.
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
최소 길이가 높을수록 메모리 할당이 줄어 듭니다.
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 |
인코더 : "고급" | -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 |
캐시 : 사실 | +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 라이센스에 따라 출시되었습니다