محلل ومُسلسل ومحرك بحث خفيف الوزن وفعال يشبه لوسين.
تم إنشاء Liqe في الأصل لتمكين تصفية سجل Roarr عبر cli. لقد قمت منذ ذلك الحين بتلميع هذا المشروع باعتباره هواية/تمرينًا فكريًا. لقد رأيت أنه يتم اعتماده بواسطة العديد من تطبيقات CLI وتطبيقات الويب التي تتطلب بحثًا متقدمًا. على حد علمي، فهو حاليًا محلل بناء الجملة والمتسلسل الأكثر اكتمالًا في JavaScript، مثل Lucene، بالإضافة إلى محرك بحث متوافق في الذاكرة.
تشمل حالات استخدام Liqe ما يلي:
لاحظ أنه يتم التعامل مع Liqe AST كواجهة برمجة تطبيقات عامة، أي أنه يمكن للمرء تنفيذ آلية البحث الخاصة به والتي تستخدم لغة الاستعلام 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 Query (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
ابحث عن كلمة "foo" في حقل name
.
name :foo
ابحث عن قيم حقل name
المطابقة /foo/i
regex.
name :/foo / i
ابحث عن قيم حقل name
المطابقة لنمط حرف البدل f*o
.
name :f * o
ابحث عن قيم حقل name
المطابقة f?o
أحرف البدل.
name :f? o
ابحث عن عبارة "foo bar" في حقل name
(حساس لحالة الأحرف).
name :"foo bar"
ابحث عن قيمة تساوي 100 في حقل height
.
height : = 100
ابحث عن قيمة أكبر من 100 في حقل height
.
height :>100
ابحث عن قيمة أكبر من أو تساوي 100 في حقل height
.
height :>=100
ابحث عن قيمة أكبر أو تساوي 100 وأقل أو تساوي 200 في حقل height
.
height : [ 100 TO 200 ]
ابحث عن قيمة أكبر من 100 وأقل من 200 في حقل height
.
height : { 100 TO 200 }
ابحث عن أي كلمة تبدأ بـ "foo" في حقل name
.
name :foo *
ابحث عن أي كلمة تبدأ بـ "foo" وتنتهي بـ "bar" في حقل name
.
name :foo * bar
ابحث عن أي كلمة تبدأ بـ "foo" في حقل name
، متبوعة بحرف واحد عشوائي.
name :foo?
ابحث عن أي كلمة تبدأ بـ "foo"، متبوعة بحرف واحد عشوائي وتنتهي فورًا بـ "bar" في حقل name
.
name :foo? bar
ابحث عن عبارة "foo bar" في حقل name
وعن عبارة "quick fox" في حقل bio
.
name :"foo bar" AND bio : "quick fox"
ابحث إما عن عبارة "foo bar" في حقل name
وعن عبارة "quick fox" في حقل bio
، أو عن كلمة "fox" في حقل name
.
( name :"foo bar" AND bio : "quick fox" ) OR name : fox
يسمح Serializer بتحويل رموز 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
. قم بتشغيل المعيار مرة أخرى بعد إجراء أية تغييرات. قبل إجراء التغييرات، تأكد من عدم تأثر الأداء سلبًا.