Este é um mecanismo de pesquisa projetado para sites de conteúdo com suporte simplificado, porém funcional, à morfologia inglesa e russa. Ele indexa seu conteúdo e fornece uma pesquisa de texto completo.
Banco de dados | Testes |
---|---|
MySQL 5.6 ou posterior e MariaDB 10.2 ou posterior | |
PostgreSQL (testado nas versões 10...16) | |
SQLite (testado em 3.37.2) |
composer require s2/rose
O índice pode ser armazenado em um banco de dados ou em um arquivo. Um armazenamento serve como uma camada de abstração que oculta detalhes de implementação. Na maioria dos casos você precisa de armazenamento de banco de dados PdoStorage
.
O armazenamento é necessário para indexação e pesquisa.
$ 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_ ' );
Quando você deseja reconstruir o índice, você chama o método PdoStorage::erase()
:
$ storage -> erase ();
Ele descarta tabelas de índice (se existirem) e cria novas do zero. Este método é suficiente para atualizar para uma nova versão do Rose que pode não ser compatível com versões anteriores do índice existente.
Para processamento de linguagem natural, Rose usa lematizadores. O lematizador trunca a parte flexionada das palavras e Rose processa os radicais resultantes. Rose não possui dicionários integrados, mas inclui lematizadores heurísticos desenvolvidos por Porter. Você pode integrar qualquer outro algoritmo implementando o 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
cria o índice de pesquisa. Depende de um stemmer e de um armazenamento.
use S2 Rose Indexer ;
$ indexer = new Indexer ( $ storage , $ stemmer );
O Indexer aceita seus dados em um formato especial. Os dados devem ser agrupados na classe 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 );
O construtor de Indexable
possui 4 argumentos:
Os parâmetros opcionais que você pode fornecer incluem: palavras-chave, descrição, data, taxa de relevância e URL. Palavras-chave são indexadas e pesquisadas com maior relevância. A descrição pode ser usada para construir um snippet (veja abaixo). Sugere-se a utilização do conteúdo das metatags “palavra-chave” e “descrição”, se disponíveis, para esse fim. A URL pode ser uma string arbitrária.
O método Indexer::index()
é usado para adicionar e atualizar o índice. Se o conteúdo permanecer inalterado, este método ignora a operação. Caso contrário, o conteúdo será removido e indexado novamente.
Ao remover uma página do site, basta ligar
$ indexer -> removeById ( $ externalId , $ instanceId );
Os resultados da pesquisa de texto completo podem ser obtidos por meio da classe Finder
. $resultSet->getItems()
retorna todas as informações sobre itens de conteúdo e sua relevância.
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>.'
}
Modifique o objeto Query
para usar uma paginação:
$ 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)
Forneça o ID da instância para limitar o escopo da pesquisa com um subsistema:
$ resultSet = $ finder -> find (( new Query ( ' content ' ))-> setInstanceId ( 1 ));
foreach ( $ resultSet -> getItems () as $ item ) {
// first iteration only:
$ item -> getId (); // 'id_1'
$ item -> getInstanceId (); // 1
}
É uma prática comum destacar as palavras encontradas nos resultados da pesquisa. Você pode obter o título destacado:
$ resultSet = $ finder -> find ( new Query ( ' title ' ));
$ resultSet -> getItems ()[ 0 ]-> getHighlightedTitle ( $ stemmer ); // 'Test page <i>title</i>'
Este método requer o lematizador, pois leva em consideração a morfologia e destaca todas as formas das palavras. Por padrão, as palavras são destacadas em itálico. Você pode alterar o modelo de destaque chamando $finder->setHighlightTemplate('<b>%s</b>')
.
Snippets são pequenos fragmentos de texto contendo palavras encontradas e exibidos em uma página de resultados de pesquisa. Rose processa o conteúdo indexado e seleciona as frases que melhor correspondem.
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>.'
As palavras nos trechos são destacadas da mesma forma que nos títulos.
Se a construção de snippets demorar muito, tente usar a paginação para reduzir o número de snippets processados.
As instâncias podem ser úteis para restringir o escopo da pesquisa.
Por exemplo, você pode tentar indexar postagens de blog com instance_id = 1
e comentários com instance_id = 2
. Então você pode executar consultas com diferentes restrições:
(new Query('content'))->setInstanceId(1)
pesquisa em postagens de blog,(new Query('content'))->setInstanceId(2)
pesquisa através de comentários,(new Query('content'))
pesquisa em todos os lugares. Ao indexar, se você omitir instance_id ou fornecer instance_id === null
, um valor 0
será usado internamente. Esse conteúdo só pode corresponder a consultas sem restrições de instance_id.
Rose foi projetado para sites e aplicativos da web. Ele suporta o formato HTML do conteúdo por padrão. Contudo, é possível estender o código para suportar outros formatos (por exemplo, texto simples, markdown). Isso pode ser feito criando um extrator personalizado:
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 ());
O PdoStorage tem a capacidade de identificar itens semelhantes dentro de todo o conjunto de itens indexados.
Considere um cenário onde você tem um blog e suas postagens são indexadas usando Rose. Esse recurso específico permite que você escolha um conjunto de outras postagens para cada postagem individual, permitindo que os visitantes explorem o conteúdo relacionado.
A estrutura de dados dentro do índice de texto completo é adequada para a tarefa de seleção de postagens semelhantes. Simplificando, a pesquisa regular envolve a seleção de postagens relevantes com base nas palavras de uma consulta de pesquisa, enquanto as recomendações de postagens envolvem a seleção de outras postagens com base nas palavras presentes em uma determinada postagem.
Você pode recuperar recomendações invocando o seguinte método:
$ 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.',
// ],
Observação
As recomendações são suportadas em bancos de dados MySQL e PostgreSQL. Eles não são implementados no SQLite devido ao suporte SQL limitado.