輕量級、高效能的類似 Lucene 的解析器、序列化器和搜尋引擎。
最初建構 Liqe 是為了透過 cli 啟用 Roarr 日誌過濾。從那時起,我一直將這個專案作為一種愛好/智力練習來完善。我已經看到它被各種需要高級搜尋的 CLI 和 Web 應用程式所採用。據我所知,它是目前 JavaScript 中最完整的類別 Lucene 語法解析器和序列化器,也是相容的記憶體搜尋引擎。
Liqe 用例包括:
請注意,Liqe AST 被視為公共 API,即,人們可以使用 Liqe 查詢語言 (LQL) 實現自己的搜尋機制。
import {
filter ,
highlight ,
parse ,
test ,
} from 'liqe' ;
const persons = [
{
height : 180 ,
name : 'John Morton' ,
} ,
{
height : 175 ,
name : 'David Barker' ,
} ,
{
height : 170 ,
name : 'Thomas Castro' ,
} ,
] ;
過濾集合:
filter ( parse ( 'height:>170' ) , persons ) ;
// [
// {
// height: 180,
// name: 'John Morton',
// },
// {
// height: 175,
// name: 'David Barker',
// },
// ]
測試單一物件:
test ( parse ( 'name:John' ) , persons [ 0 ] ) ;
// true
test ( parse ( 'name:David' ) , persons [ 0 ] ) ;
// false
突出顯示匹配字段和子字串:
highlight ( parse ( 'name:john' ) , persons [ 0 ] ) ;
// [
// {
// path: 'name',
// query: /(John)/,
// }
// ]
highlight ( parse ( 'height:180' ) , persons [ 0 ] ) ;
// [
// {
// path: 'height',
// }
// ]
Liqe 使用 Liqe 查詢語言 (LQL),該語言深受 Lucene 的啟發,但以各種方式對其進行了擴展,以提供更強大的搜尋體驗。
# search for "foo" term anywhere in the document (case insensitive)
foo
# search for "foo" term anywhere in the document (case sensitive)
'foo'
"foo"
# search for "foo" term in `name` field
name :foo
# search for "foo" term in `full name` field
'full name' : foo
"full name" : foo
# search for "foo" term in `first` field, member of `name`, i.e.
# matches {name: {first: 'foo'}}
name . first :foo
# search using regex
name :/foo /
name :/ foo / o
# search using wildcard
name :foo * bar
name :foo? bar
# boolean search
member :true
member :false
# null search
member :null
# search for age =, >, >=, <, <=
height : = 100
height :>100
height :>=100
height :<100
height :<=100
# search for height in range (inclusive, exclusive)
height : [ 100 TO 200 ]
height : { 100 TO 200 }
# boolean operators
name :foo AND height : = 100
name :foo OR name : bar
# unary operators
NOT foo
- foo
NOT foo : bar
- foo :bar
name :foo AND NOT ( bio :bar OR bio : baz )
# implicit AND boolean operator
name :foo height : = 100
# grouping
name :foo AND ( bio :bar OR bio : baz )
在任何欄位中搜尋單字“foo”(不區分大小寫)。
foo
在name
欄位中搜尋單字“foo”。
name :foo
搜尋與/foo/i
正規表示式相符的name
欄位值。
name :/foo / i
搜尋與f*o
通配符模式相符的name
欄位值。
name :f * o
搜尋與f?o
通配符模式相符的name
欄位值。
name :f? o
在name
欄位中搜尋短語“foo bar”(區分大小寫)。
name :"foo bar"
在height
欄位中搜尋等於 100 的值。
height : = 100
在height
欄位中搜尋大於 100 的值。
height :>100
在height
欄位中搜尋大於或等於 100 的值。
height :>=100
在height
欄位中搜尋大於或等於 100 且小於或等於 200 的值。
height : [ 100 TO 200 ]
在height
欄位中搜尋大於 100 且小於 200 的值。
height : { 100 TO 200 }
在name
欄位中搜尋以“foo”開頭的任何單字。
name :foo *
在name
欄位中搜尋以“foo”開頭並以“bar”結尾的任何單字。
name :foo * bar
在name
欄位中搜尋以“foo”開頭,後面跟著單個任意字元的任何單字。
name :foo?
在name
欄位中搜尋以“foo”開頭、後面跟著單個任意字元並立即以“bar”結尾的任何單字。
name :foo? bar
在name
欄位中搜尋短語“foo bar”,並在bio
欄位中搜尋短語“quick Fox”。
name :"foo bar" AND bio : "quick fox"
在name
欄位中搜尋短語“foo bar”並在bio
欄位中搜尋短語“quick Fox”,或在name
欄位中搜尋單字“fox”。
( name :"foo bar" AND bio : "quick fox" ) OR name : fox
序列化器允許將 Liqe 令牌轉換回原始搜尋查詢。
import {
parse ,
serialize ,
} from 'liqe' ;
const tokens = parse ( 'foo:bar' ) ;
// {
// expression: {
// location: {
// start: 4,
// },
// quoted: false,
// type: 'LiteralExpression',
// value: 'bar',
// },
// field: {
// location: {
// start: 0,
// },
// name: 'foo',
// path: ['foo'],
// quoted: false,
// type: 'Field',
// },
// location: {
// start: 0,
// },
// operator: {
// location: {
// start: 3,
// },
// operator: ':',
// type: 'ComparisonOperator',
// },
// type: 'Tag',
// }
serialize ( tokens ) ;
// 'foo:bar'
import {
type BooleanOperatorToken ,
type ComparisonOperatorToken ,
type EmptyExpression ,
type FieldToken ,
type ImplicitBooleanOperatorToken ,
type ImplicitFieldToken ,
type LiteralExpressionToken ,
type LogicalExpressionToken ,
type RangeExpressionToken ,
type RegexExpressionToken ,
type TagToken ,
type UnaryOperatorToken ,
} from 'liqe' ;
有 11 個 AST 標記描述已解析的 Liqe 查詢。
如果您正在建立序列化器,則必須實作所有這些序列化器以完全覆寫所有可能的查詢輸入。請參閱內建序列化器的範例。
import {
isSafeUnquotedExpression ,
} from 'liqe' ;
/**
* Determines if an expression requires quotes.
* Use this if you need to programmatically manipulate the AST
* before using a serializer to convert the query back to text.
*/
isSafeUnquotedExpression ( expression : string ) : boolean ;
不支援以下 Lucene 功能:
如果出現語法錯誤,Liqe 會拋出SyntaxError
。
import {
parse ,
SyntaxError ,
} from 'liqe' ;
try {
parse ( 'foo bar' ) ;
} catch ( error ) {
if ( error instanceof SyntaxError ) {
console . error ( {
// Syntax error at line 1 column 5
message : error . message ,
// 4
offset : error . offset ,
// 1
offset : error . line ,
// 5
offset : error . column ,
} ) ;
} else {
throw error ;
}
}
考慮使用highlight-words
套件來突出顯示 Liqe 匹配項。
如果要修改解析器,請使用npm run watch
在監視模式下執行編譯器。
在進行任何更改之前,請使用npm run benchmark
捕獲計算機上的當前基準測試。進行任何更改後再次執行基準測試。在提交更改之前,請確保效能不會受到負面影響。