นี่คือเครื่องมือค้นหาที่ออกแบบมาสำหรับไซต์เนื้อหาที่มีการรองรับสัณฐานวิทยาภาษาอังกฤษและรัสเซียที่เรียบง่ายแต่ใช้งานได้ มันจัดทำดัชนีเนื้อหาของคุณและให้การค้นหาข้อความแบบเต็ม
ฐานข้อมูล | การทดสอบ |
---|---|
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 ใช้สเต็มเมอร์ ก้านตัดจะตัดส่วนที่โค้งงอของคำออก และโรสจะประมวลผลลำต้นที่เกิด Rose ไม่มีพจนานุกรมในตัว แต่มีต้นกำเนิดจากการศึกษาสำนึกที่พัฒนาโดย Porter คุณสามารถรวมอัลกอริธึมอื่นๆ ได้โดยใช้ 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 );
Indexer ยอมรับข้อมูลของคุณในรูปแบบพิเศษ ข้อมูลจะต้องถูกห่อไว้ในคลาส 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 หรือระบุ instance_id === null
ค่า 0
จะถูกนำมาใช้เป็นการภายใน เนื้อหาดังกล่าวสามารถจับคู่คำค้นหาโดยไม่มีข้อจำกัด instance_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 ที่จำกัด