هذا محرك بحث مصمم لمواقع المحتوى مع دعم مورفولوجي مبسط وعملي للغة الإنجليزية والروسية. يقوم بفهرسة المحتوى الخاص بك ويوفر بحثًا عن النص الكامل.
قاعدة البيانات | الاختبارات |
---|---|
MySQL 5.6 أو الأحدث وMariaDB 10.2 أو الأحدث | |
PostgreSQL (تم اختباره على الإصدارات 10...16) | |
SQLite (تم اختباره على الإصدار 3.37.2) |
composer require s2/rose
يمكن تخزين الفهرس في قاعدة بيانات أو في ملف. يعمل التخزين كطبقة تجريد تخفي تفاصيل التنفيذ. في معظم الحالات تحتاج إلى تخزين قاعدة البيانات PdoStorage
.
التخزين مطلوب لكل من الفهرسة والبحث.
$ pdo = new PDO ( ' mysql:host=127.0.0.1;dbname=s2_rose_test;charset=utf8 ' , ' username ' , ' passwd ' );
$ pdo -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );
use S2 Rose Storage Database PdoStorage ;
$ storage = new PdoStorage ( $ pdo , ' table_prefix_ ' );
عندما تريد إعادة بناء الفهرس، يمكنك استدعاء الأسلوب PdoStorage::erase()
:
$ storage -> erase ();
يقوم بإسقاط جداول الفهرس (إذا كانت موجودة) ويقوم بإنشاء جداول جديدة من البداية. هذه الطريقة كافية للترقية إلى إصدار جديد من Rose الذي قد لا يكون متوافقًا مع الفهرس الموجود.
لمعالجة اللغة الطبيعية، يستخدم روز السيقان. يقوم الجذع باقتطاع الجزء المصروف من الكلمات، وتقوم روز بمعالجة السيقان الناتجة. لا تحتوي لغة Rose على قواميس مدمجة، ولكنها تتضمن أصولًا إرشادية طورها بورتر. يمكنك دمج أي خوارزمية أخرى من خلال تطبيق StemmerInterface.
use S2 Rose Stemmer PorterStemmerEnglish ;
use S2 Rose Stemmer PorterStemmerRussian ;
// For optimization primary language goes first (in this case Russian)
$ stemmer = new PorterStemmerRussian ( new PorterStemmerEnglish ());
يقوم Indexer
ببناء فهرس البحث. ذلك يعتمد على الجذعية والتخزين.
use S2 Rose Indexer ;
$ indexer = new Indexer ( $ storage , $ stemmer );
يقبل المفهرس بياناتك بتنسيق خاص. يجب أن تكون البيانات ملفوفة في فئة Indexable
:
use S2 Rose Entity Indexable ;
// Main parameters
$ indexable = new Indexable (
' id_1 ' , // External ID - an identifier in your system
' Test page title ' , // Title
' This is the first page to be indexed. I have to make up a content. ' ,
1 // Instance ID - an optional ID of your subsystem
);
// Other optional parameters
$ indexable
-> setKeywords ( ' singlekeyword, multiple keywords ' ) // The same as Meta Keywords
-> setDescription ( ' Description can be used in snippets ' ) // The same as Meta Description
-> setDate ( new DateTime ( ' 2016-08-24 00:00:00 ' ))
-> setUrl ( ' url1 ' )
-> setRelevanceRatio ( 3.14 ) // Multiplier for important pages
;
$ indexer -> index ( $ indexable );
$ indexable = new Indexable (
' id_2 ' ,
' Test page title 2 ' ,
' This is the second page to be indexed. Let ' s compose something new. '
);
$ indexable -> setKeywords ( ' content, page ' );
$ indexer -> index ( $ indexable );
يحتوي مُنشئ Indexable
على 4 وسيطات:
تتضمن المعلمات الاختيارية التي يمكنك توفيرها ما يلي: الكلمات الرئيسية، والوصف، والتاريخ، ونسبة الملاءمة، وعنوان URL. تتم فهرسة الكلمات الرئيسية والبحث عنها ذات صلة أعلى. يمكن استخدام الوصف لإنشاء مقتطف (انظر أدناه). يُقترح استخدام محتوى العلامات الوصفية "الكلمة الرئيسية" و"الوصف"، إن وجدت، لهذا الغرض. يمكن أن يكون عنوان URL عبارة عن سلسلة عشوائية.
يتم استخدام طريقة Indexer::index()
لإضافة الفهرس وتحديثه. إذا لم يتغير المحتوى، فستتخطى هذه الطريقة العملية. وبخلاف ذلك، ستتم إزالة المحتوى وفهرسته مرة أخرى.
عند إزالة صفحة من الموقع، ما عليك سوى الاتصال
$ indexer -> removeById ( $ externalId , $ instanceId );
يمكن الحصول على نتائج البحث عن النص الكامل عبر فئة Finder
. $resultSet->getItems()
يُرجع كافة المعلومات حول عناصر المحتوى وأهميتها.
use S2 Rose Finder ;
use S2 Rose Entity Query ;
$ finder = new Finder ( $ storage , $ stemmer );
$ resultSet = $ finder -> find ( new Query ( ' content ' ));
foreach ( $ resultSet -> getItems () as $ item ) {
// first iteration: second iteration:
$ item -> getId (); // 'id_2' 'id_1'
$ item -> getInstanceId (); // null 1
$ item -> getTitle (); // 'Test page title 2' 'Test page title'
$ item -> getUrl (); // '' 'url1'
$ item -> getDescription (); // '' 'Description can be used in snippets'
$ item -> getDate (); // null new DateTime('2016-08-24 00:00:00')
$ item -> getRelevance (); // 4.1610856664112195 0.26907154598642522
$ item -> getSnippet (); // 'This is the second page...' 'I have to make up a <i>content</i>.'
}
قم بتعديل كائن Query
لاستخدام ترقيم الصفحات:
$ query = new Query ( ' content ' );
$ query
-> setLimit ( 10 ) // 10 results per page
-> setOffset ( 20 ) // third page
;
$ resultSet = $ finder -> find ( $ query );
$ resultSet -> getTotalCount (); // Returns total amount of found items (for pagination links)
قم بتوفير معرف المثيل للحد من نطاق البحث باستخدام نظام فرعي:
$ resultSet = $ finder -> find (( new Query ( ' content ' ))-> setInstanceId ( 1 ));
foreach ( $ resultSet -> getItems () as $ item ) {
// first iteration only:
$ item -> getId (); // 'id_1'
$ item -> getInstanceId (); // 1
}
من الممارسات الشائعة إبراز الكلمات التي تم العثور عليها في نتائج البحث. يمكنك الحصول على العنوان المميز:
$ resultSet = $ finder -> find ( new Query ( ' title ' ));
$ resultSet -> getItems ()[ 0 ]-> getHighlightedTitle ( $ stemmer ); // 'Test page <i>title</i>'
تتطلب هذه الطريقة وجود الجذع لأنه يأخذ في الاعتبار الشكل الشكلي ويسلط الضوء على جميع أشكال الكلمة. افتراضيًا، يتم تمييز الكلمات بخط مائل. يمكنك تغيير قالب التمييز عن طريق استدعاء $finder->setHighlightTemplate('<b>%s</b>')
.
المقتطفات عبارة عن أجزاء نصية صغيرة تحتوي على كلمات تم العثور عليها ويتم عرضها في صفحة نتائج البحث. يقوم Rose بمعالجة المحتوى المفهرس ويختار أفضل الجمل المطابقة.
use S2 Rose Entity ExternalContent ;
use S2 Rose Snippet SnippetBuilder ;
$ finder -> setSnippetLineSeparator ( ' · ' ); // Set snippet line separator. Default is '... '.
$ resultSet -> getItems ()[ 0 ]-> getSnippet ();
// 'I have to make up a <i>content</i>. · I have changed the <i>content</i>.'
يتم تمييز الكلمات الموجودة في المقتطفات بنفس الطريقة كما في العناوين.
إذا استغرق إنشاء المقتطفات الكثير من الوقت، فحاول استخدام ترقيم الصفحات لتقليل عدد المقتطفات التي تتم معالجتها.
يمكن أن تكون المثيلات مفيدة لتقييد نطاق البحث.
على سبيل المثال، يمكنك محاولة فهرسة منشورات المدونة باستخدام instance_id = 1
والتعليقات باستخدام instance_id = 2
. ثم يمكنك تشغيل الاستعلامات بقيود مختلفة:
(new Query('content'))->setInstanceId(1)
يبحث في منشورات المدونة،(new Query('content'))->setInstanceId(2)
يبحث من خلال التعليقات،(new Query('content'))
يبحث في كل مكان. عند الفهرسة، إذا قمت بحذف معرّف المثيل أو تقديم instance_id === null
، فسيتم استخدام القيمة 0
داخليًا. يمكن لمثل هذا المحتوى أن يطابق الاستعلامات فقط بدون قيود example_id.
تم تصميم Rose لمواقع الويب وتطبيقات الويب. وهو يدعم تنسيق HTML للمحتوى بشكل افتراضي. ومع ذلك، فمن الممكن توسيع التعليمات البرمجية لدعم تنسيقات أخرى (على سبيل المثال، نص عادي، تخفيض السعر). يمكن القيام بذلك عن طريق إنشاء مستخرج مخصص:
use S2 Rose Extractor ExtractorInterface ;
use S2 Rose Indexer ;
class CustomExtractor implements ExtractorInterface
{
// ...
// Please refer to the source code
// to figure out how to create an extractor.
}
$ indexer = new Indexer ( $ storage , $ stemmer , new CustomExtractor (), new Logger ());
يتمتع PdoStorage بالقدرة على تحديد العناصر المماثلة ضمن مجموعة العناصر المفهرسة بأكملها.
فكر في سيناريو حيث يكون لديك مدونة ويتم فهرسة منشوراتها باستخدام Rose. تتيح لك هذه الميزة تحديدًا اختيار مجموعة من المنشورات الأخرى لكل مشاركة على حدة، مما يتيح للزائرين استكشاف المحتوى ذي الصلة.
تعتبر بنية البيانات داخل فهرس النص الكامل مناسبة تمامًا لمهمة اختيار منشورات مماثلة. لتبسيط الأمر، يستلزم البحث العادي اختيار المنشورات ذات الصلة بناءً على الكلمات من استعلام بحث، في حين تتضمن توصيات النشر اختيار منشورات أخرى بناءً على الكلمات الموجودة في منشور معين.
يمكنك استرداد التوصيات عن طريق استدعاء الطريقة التالية:
$ similarItems = $ readStorage -> getSimilar ( new ExternalId ( ' id_2 ' ));
// The result contains the following data:
// $similarItems[0] = [
// 'tocWithMetadata' => new TocEntryWithMetadata(...),
// 'external_id' => 'id_1',
// 'instance_id' => '1',
// 'title' => 'Test page title',
// 'snippet' => 'This is the first page to be indexed.',
// 'snippet2' => 'I have to make up a content.',
// ],
ملحوظة
التوصيات مدعومة في قواعد بيانات MySQL وPostgreSQL. لم يتم تنفيذها في SQLite بسبب دعم SQL المحدود.