Open Search Server Client
Open Search Server Client
com/jaeksoft/opensearchserv
er-php-client
Fully integrated solution: build your index, crawl your websites, filesystem or
databases, configure your search queries
Search features:
o Full-text, boolean and phonetic search
o Outer and inner join
o Clusters with faceting & collapsing
o Filtered search (date, distance)
o Geolocation using square or radius
o Several spell-checking algorithms
o Relevance customization
o Suggestion (auto-completion)
Indexation features:
o 17 languages
o Crawlers: web, filesystem (local, remote), database, mailboxes
o Special analysis for each language
o Numerous filters: n-gram, lemmatization, shingle, elisions, stripping
diacritic, Etc.
o Automatic language detection
o Named entity recognition
Setup
mkdir ossphp_sandbox
cd ossphp_sandbox
"require": {
"opensearchserver/opensearchserver": "3.0.*"
}
mkdir web
cd web
echo "<?php include_once '../vendor/autoload.php';" > index.php
Quick start
A global handler must be created. It will be used to submit every request to your
OpenSearchServer instance:
$url
= '<instance URL>';
Note character *: it means crawler will be allowed to follow any URL starting by these
patterns.
Add some start URLs for crawler:
$request = new OpenSearchServer\Crawler\Web\Url\Insert();
$request->index('first_index')
->urls('http://www.my-website.com', 'http://www.your-website.net');
$oss_api->submit($request);
Here * is not used since real URL are given to crawler: it will use these URLs as first
entry points.
Start crawler:
$request = new OpenSearchServer\Crawler\Web\Start();
$request->index('first_index');
$oss_api->submit($request);
Index documents
While crawler is running some documents can still be manually indexed:
$document = new OpenSearchServer\Document\Document();
$document ->lang(OpenSearchServer\Request::LANG_FR)
->field('title','The Count Of Monte Cristo')
->field('url', '1');
$document2 = new OpenSearchServer\Document\Document();
$document2 ->lang(OpenSearchServer\Request::LANG_FR)
->field('title','The Three Musketeers')
->field('url', '2');
$request = new OpenSearchServer\Document\Put();
$request->index('first_index')
->addDocuments(array($document, $document2));
$oss_api->submit($request);
Client Documentation
Table of contents
OpenSearchServer\Response\Response
OpenSearchServer\Response\ResponseIterable
OpenSearchServer\Response\SearchResult
OpenSearchServer\Response\MoreLikeThisResult
OpenSearchServer\Response\SpellCheckResult
Instance monitoring
Configure schema
o Create a field
o Create full schema
o Get list of fields
o Get details of a specific field
o Delete a field
o Set default and unique field for an index
Analyzers
o Create an analyzer
Web crawler
o Patterns
File crawler
o Start file crawler
o Stop file crawler
o Get file crawler status
o File repositories
Local file
FTP
SMB/CIFS
Swift
REST crawler
o List existing REST crawlers
o Execute a REST crawler
Autocompletion
o Create an autocompletion
o Build autocompletion
Documents
o Push documents
o Delete documents
o Delete documents by query
o Search(pattern)
Search templates
o List search template
o Get details of a search template
o Delete a search template
Synonyms
o Create a list of synonyms
o Check if a list of synonyms exists
o Get existing lists of synonyms
o Get synonyms of a list
o Delete a list of synonyms
Spellcheck queries
o Get list of spellcheck query templates
o Delete a spellcheck query template
o Execute a spellcheck search
Scheduler
o Get status of a scheduler job
o Execute a scheduler job
Replication
o Get list of replications
o Get details about one replication
o Create or update a replication
o Start a replication
o Delete a replication
Create an handler
$url
= '<instance URL>';
$app_key = '<API key>';
$login
= '<login>';
$oss_api = new OpenSearchServer\Handler(array('url' => $url, 'key' => $app_key,
'login' => $login));
Create a request
Several types of objects are available, each being a mapping to one API. For instance
objects of typeOpenSearchServer\Index\Create will be used to create index and objects
of typeOpenSearchServer\Search\Field\Search will be used to search for documents.
Each request object is a child of the abstract parent class OpenSearchServer\Request.
For example here is the code to create a request that wil create an index when sent to
an OpenSearchServer instance:
$request = new OpenSearchServer\Index\Create();
After being created each type of request must be configured in a particular way,
depending on its type, by calling some methods.
For example this code will tell OpenSearchServer to name the new index "first_index":
$request->index('first_index');
Important note:
method index() is really important and is shared by almost every type of requests.
In the case of index creation it serves to give a name to new index and in almost
every other request it will be used to configure the index on which API call must
be made.
This method will not be documented further but will be displayed in code examples
when needed.
Once configured request must be sent to an OpenSearchServer instance thanks to the
handler created before:
$response = $oss_api->submit($request);
},
{
"field": "title",
"tag": "em",
"separator": "...",
"maxSize": 200,
"maxNumber": 1,
"fragmenter": "NO"
"field": "content",
"tag": "em",
"separator": "...",
"maxSize": 200,
"maxNumber": 1,
"fragmenter": "SENTENCE"
}
],
"enableLog": false,
"searchFields": [
{
"field": "title",
"mode": "PHRASE",
"boost": 3
},
{
"field": "content",
"mode": "PHRASE",
"boost": 4
},
{
"field": "titleExact",
"mode": "PHRASE",
"boost": 5
},
{
"field": "contentExact",
"mode": "PHRASE",
"boost": 6
}
]
}
JSON;
$request = new OpenSearchServer\Search\Field\Put(null, $json);
$request->index('00__test_web')
->template('test_with_json_text');
$response = $oss_api->submit($request);
Several types of responses can be returned by submit(). Internally this method uses a
Factory that builds a response depending on the type of Request given.
OpenSearchServer\Response\Response
Main Response class.
Methods:
o isSuccess(): true if everything went well, false if there was a problem
during execution of request.
o getInfo(): some requests can return some information. For example Index
deleted: 00__test_file.
Example:
OpenSearchServer\Response\ResponseIterable
Extends OpenSearchServer\Response\Response. Used when response contain iterable
values. This class implements \Iterator and can thus be used in a loop structure.
o OpenSearchServer\Crawler\Rest\GetList
o OpenSearchServer\Index\GetList
o OpenSearchServer\Field\GetList
o OpenSearchServer\SearchTemplate\GetList
o OpenSearchServer\MoreLikeThis\GetList
o OpenSearchServer\Analyzer\GetList
o OpenSearchServer\Synonyms\GetList
o OpenSearchServer\Crawler\Rest\GetList
o OpenSearchServer\Crawler\Web\Patterns\Exclusion\GetList
o OpenSearchServer\Crawler\Web\Patterns\Inclusion\GetList
OpenSearchServer\Response\SearchResult
Extends OpenSearchServer\Response\ResponseIterable. Used for search results.
Methods:
o getResults(): return array of objects of type
OpenSearchServer\Response\Result
o getFacets(): return an array of facets for this query. Each facet is an array
with key being name of field and values being array in the form <text
value> => <number of occurrences>
Example: this class being iterable it can also be used in a loop structure:
$request = new OpenSearchServer\Search\Field\Search();
$request->index('index_name')
->query('house')
//using a pre-configured query template
->template('search');
$results = $oss_api->submit($request);
echo 'Total number of results: ' . $results->getTotalNumberFound() . '<br/>';
echo 'Number of results in this set of results: ' . $results->getNumberOfResults();
foreach($results as $key => $result) {
echo '<hr/>Result #'.$key.': <br/>';
print_r($result);
}
Methods:
o getPos():
o getScore():
o getCollapsedCount():
o getField($fieldName, $returnFirstValueOnly = true): return value of a
field
$fieldName is the name of the field from which the snippet has
have been asked the query even if they have no value for this
result.
Example:
OpenSearchServer\Response\MoreLikeThisResult
This kind of response looks like OpenSearchServer\Response\SearchResult but with
fewer features, since results returned by MoreLikeThis query are simpler.
Methods:
o getResults(): return array of objects of type
OpenSearchServer\Response\Result
o getQuery(): return query
OpenSearchServer\Response\SpellCheckResult
This response is returned by SpellCheck queries. It is used to access spell check
suggestions for each asked field.
Example:
$request = new OpenSearchServer\SpellCheck\Search();
$request->index('index_name')
->query('houze')
->template('spellcheck');
$response = $oss_api->submit($request);
var_dump($response->getBestSpellSuggestion('title'));
var_dump($response->getSpellSuggestionsArray('title'));
Available methods:
array (size=3)
'houze' =>
array (size=2)
'house' => int 12
'houzz' => int 6
Template FILE_CRAWLER:
Delete an index
Go to API documentation for this method
Instance monitoring
Several instance-wide monitoring properties can be retrieved:
$request = new OpenSearchServer\Monitor\Monitor();
$request->full();
$response = $oss_api->submit($request);
echo '<ul>';
foreach($response as $propName => $value) {
echo '<li>'.$propName.': '.$value.'</li>';
}
echo '</ul>';
availableProcessors: 4
freeMemory: 38656976
memoryRate: 12.958230285108
maxMemory: 1879048192
totalMemory: 298319872
indexCount: 59
freeDiskSpace: 24181137408
freeDiskRate: 23.061161199939
java.vm.version: 24.51-b03
java.vendor.url: http://java.oracle.com/
...
...
Available methods:
Configure schema
In OpenSearchServer each index must have a schema. A schema is a list of fields,
each with some properties.
Create a field
Go to API documentation for this method
$request = new OpenSearchServer\Field\Create();
$request->index('index_name')
->name('titleStandard')
->indexed(true)
->analyzer('StandardAnalyzer')
->stored(true)
->copyOf('title');
$response = $oss_api->submit($request);
Available methods:
stored(boolean $stored): tells whether or not this field must be stored. Stored
field can return their original values in search queries, even if some Analyzers
transformed it.
$json = <<<JSON
[
{
"name": "uniqueId",
"indexed": "YES",
"stored": "NO"
},
{
"name": "title",
"indexed": "YES",
"stored": "YES",
"analyzer": "TextAnalyzer"
},
{
"name": "description",
"indexed": "YES",
"stored": "YES",
"analyzer": "TextAnalyzer"
},
{
"name": "descriptionStandard",
"indexed": "YES",
"stored": "NO",
"analyzer": "StandardAnalyzer",
"copyOf": [
"description"
]
}
]
JSON;
$request = new OpenSearchServer\Field\CreateBulk(null, $json);
$request->index('00__test_schema');
$response = $oss_api->submit($request);
Available methods:
Delete a field
Go to API documentation for this method
$request = new OpenSearchServer\Field\Delete();
$request->index('index_name')
->name('titleStandard');
$response = $oss_api->submit($request);
Available methods:
$response = $oss_api->submit($request);
Available methods:
Analyzers
Create an analyzer
Go to API documentation for this method
Analyzer can be created or updated using some JSON Text or JSON array of values
with object of type OpenSearchServer\Analyzer\Create.
$json = <<<JSON
{
"queryTokenizer":{"name":"KeywordTokenizer"},
"indexTokenizer":{"name":"KeywordTokenizer"},
"filters":[
{
"name":"ShingleFilter",
"properties":{
"max_shingle_size":"5",
"token_separator":" ",
"min_shingle_size":"1"
},
"scope":"QUERY_INDEX"
},
{
"name":"PrefixSuffixStopFilter",
"properties":{
"prefixList":"English stop words",
"ignore_case":"true",
"token_separator":" ",
"suffixList":"English stop words"
},
"scope":"QUERY_INDEX"
}
]
}
JSON;
$request = new OpenSearchServer\Analyzer\Create(null, $json);
$request->index('index_name')
->name('TestAnalyzer');
$response = $oss_api->submit($request);
var_dump($response->isSuccess());
Available methods:
Available methods:
Web Crawler
Patterns
->patterns(array('http://www.exclude1.com/page1',
'http://www.exclude2.net/page1'));
$response = $oss_api->submit($request);
File crawler
Start file crawler
$request = new OpenSearchServer\Crawler\File\Start();
$request->index('index_name');
$response = $oss_api->submit($request);
Available method:
File repositories
Every type of location share some common methods for insertion:
...
->path('/files/invoices')
->ignoreHiddenFile(true)
->includeSubDirectory(true)
->enabled(true)
->delay(100);
...
Available methods:
path(string $path)
ignoreHiddenFile(boolean $ignoreHiddenFile)
includeSubDirectory(boolean $includeSubDirectory)
Local file
Insert local file location
$request = new OpenSearchServer\Crawler\File\Repository\LocalFile\Insert();
$request->index('index_name')
->path('/archives/pdf')
->ignoreHiddenFile(true)
->includeSubDirectory(true)
->enabled(true)
->delay(100);
$response = $oss_api->submit($request);
->path('/archives/pdf');
$response = $oss_api->submit($request);
FTP
Insert FTP location
$request = new OpenSearchServer\Crawler\File\Repository\Ftp\Insert();
$request->index('index_name')
->path('/archives/office_documents')
->ignoreHiddenFile(true)
->includeSubDirectory(true)
->enabled(true)
->delay(100)
->username('user')
->password('p455w0rD')
->host('ftp.host.net')
->ssl(true);
$response = $oss_api->submit($request);
Available methods:
username(string $username)
password(string $password)
host(string $host)
Available methods:
username(string $username)
host(string $host)
ssl(boolean $isSsl): set to true if location to delete uses FTP over SSL
SMB/CIFS
Insert SMB/CIFS location
$request = new OpenSearchServer\Crawler\File\Repository\Smb\Insert();
$request->index('index_name')
->path('/archives/pdf')
->ignoreHiddenFile(true)
->includeSubDirectory(true)
->enabled(true)
->delay(100)
->username('user')
->password('p455w0rD')
->domain('mydomain')
->host('myhost.net');
$response = $oss_api->submit($request);
Available methods:
username(string $username)
password(string $password)
domain(string $domain)
host(string $host)
Available methods:
username(string $username)
domain(string $domain)
host(string $host)
Swift
Insert Swift location
$request = new OpenSearchServer\Crawler\File\Repository\Swift\Insert();
$request->index('index_name')
->path('/archives/pdf')
->ignoreHiddenFile(true)
->includeSubDirectory(true)
->enabled(true)
->delay(100)
->username('user')
->password('p455w0rD')
->tenant('mytenant')
->container('container_main')
->authUrl('http://auth.example.com')
->authType(OpenSearchServer\Crawler\File\Repository\Swift\Insert::AUTH_KEYSTONE);
$response = $oss_api->submit($request);
Available methods:
username(string $username)
password(string $password)
tenant(string $tenant)
container(string $container)
authUrl(string $authUrl)
$response = $oss_api->submit($request);
username(string $username)
container(string $container)
REST crawler
List existing REST crawlers
$request = new OpenSearchServer\Crawler\Rest\GetList();
$request->index('00__test_file');
$response = $oss_api->submit($request);
foreach($response as $key => $item) {
echo '<br/>Item #'.$key .': ';
print_r($item);
}
Available methods:
Autocompletion
Create an autocompletion
Go to API documentation for this method
Available methods:
field(string $name): name of field in main schema from which suggestion are
returned.
fields(array $fields):** helper method, calls field() for each item in array.
Build autocompletion
Go to API documentation for this method
Autocompletion sub-index need to be re-built frequently, when content on main index
changes. This can be automatized with OpenSearchServer's Schedulers or done by
calling this API.
$request = new OpenSearchServer\Autocompletion\Build();
$request->index('index_name')
->name('autocomplete');
$response = $oss_api->submit($request);
Available methods:
Query autocompletion
Go to API documentation for this method
$request = new OpenSearchServer\Autocompletion\Query();
$request->index('index_name')
->name('autocomplete')
->query('Three Musk')
->rows(10);
$response = $oss_api->submit($request);
foreach($response as $key => $item) {
echo '<br/>Item #'.$key .': ';
print_r($item);
}
Available methods:
Available methods:
Documents
Push documents
Go to API documentation for this method
Available methods:
field(string $name, string $value, int $boost): give value to a field, with an
optionnal boost. You would probably prefer to use boost at query time. This
method can be called several times with same $name argument to index multiple
values for one field.
Text files in CSV or TTL can be pushed to OpenSearchServer, with a regexp pattern to
match fields.
$data = <<<TEXT
4;The Three Musketeers;In 1625 France, d'Artagnan-a poor young nobleman-leaves his
family in Gascony and travels to Paris with the intention of joining the Musketeers of the
Guard. However, en route, at an inn in Meung-sur-Loire, an older man derides
d'Artagnan's horse and, feeling insulted, d'Artagnan demands to fight a duel with him.
The older man's companions beat d'Artagnan unconscious with a pot and a metal tong
that breaks his sword. His letter of introduction to Monsieur de Trville, the commander
of the Musketeers, is stolen. D'Artagnan resolves to avenge himself upon the man, who
is later revealed to be the Comte de Rochefort, an agent of Cardinal Richelieu, who is in
Meung to pass orders from the Cardinal to Milady de Winter, another of his agents.;en
5;Twenty Years After;The action begins under Queen Anne of Austria regency and
Cardinal Mazarin ruling. D'Artagnan, who seemed to have a promising career ahead of
him at the end of The Three Musketeers, has for twenty years remained a lieutenant in
the Musketeers, and seems unlikely to progress, despite his ambition and the debt the
queen owes him;en
6;The Vicomte de Bragelonne;The principal heroes of the novel are the musketeers. The
novel's length finds it frequently broken into smaller parts. The narrative is set between
1660 and 1667 against the background of the transformation of Louis XIV from child
monarch to Sun King.;en";
TEXT;
$request = new OpenSearchServer\Document\PutText();
$request->index('00__test_file')
->pattern('(.*?);(.*?);(.*?);(.*?)')
->data($data)
->langpos(4)
->buffersize(100)
->charset('UTF-8')
->fields(array('uri', 'title', 'content', 'lang'));
$response = $oss_api->submit($request);
Available methods:
data(string $data):
buffersize(int $bufferSize)
field(string $fieldname): one field mapping. Can be called several times to map
several fields.
fields(array $fields): help method. Calls field() for each item in array.
Delete documents
Go to API documentation for this method
$request = new OpenSearchServer\Document\Delete();
$request->index('index_name')
->field('id')
->value('3')
->values(array('4','5','6'));
$response = $oss_api->submit($request);
Available methods:
values(array $values): helper method. Call value() for each item in array.
Available methods:
One or the other of these 2 methods must be used:
Search options
Two types of search queries exist in OpenSearchServer : Search field and Search
pattern.
They both offer lots of common options and only differ in the way of specfiying searched
fields:
$request = new ...;
$request->index('index_name')
->emptyReturnsAll()
->query('house')
//set operator to use when multiple keywords
->operator(OpenSearchServer\Search\Search::OPERATOR_AND)
//set lang of keywords
->lang('FRENCH')
//enable logging
->enableLog()
//set returned fields
->returnedFields(array('title', 'url'))
//set static filter
->filter('status:1')
//set another static filter, different way
->filterField('year', '[0 TO 1990]')
//set another static filter, with yet a different way
->filterField('category', array('files', 'archives'))
//set number of results
->rows(5)
//configure sorting
->sort('date', OpenSearchServer\Search\Search::SORT_DESC)
//add a level of sorting for documents with same date
->sort('url', OpenSearchServer\Search\Search::SORT_ASC)
//set facets (min 1, multivalued field)
->facet('category', 1, true)
//set snippets
->snippet('title')
->snippet('content', 'b', '...', 200, 1,
OpenSearchServer\Search\Search::SNIPPET_SENTENCE_FRAGMENTER);
$results = $oss_api->submit($request);
Available methods:
General options:
o query(string $query): search keywords
o emptyReturnsAll(boolean $value): if set to true and keywords are empty
will return every documents of the index
Sorting options
o sort(string $field, string $direction): add a sorting on one field. Can be
called multiple times to successively sort on different fields.
o sorts(array $sorts, string $direction): helper method. Calls sort() for
each item in array.
Scoring options
o scoring(string $field, int $weight, boolean $ascending, type $type):
Facetting options
o facet(string $field, int $min = 0, boolean $multi = false, boolean
$postCollapsing = false): compute facet for one field: this will return
count of every different values for this field. Facets can be used through >getFacets() when workingh with
Filtering options
o queryFilter(string $filter): add a filter with a pattern query. For
example : lang:en.
o negativeFilter(string $filter): add a negative query filter.
o geoFilter(string $shape, string $unit, int $distance): add a geo filter.
o negativeGeoFilter(string $shape, string $unit, int $distance): add a
negative geo filter
Parameters:
beOpenSearchServer\Search\Field\Search::RELATIVE_DATE_FI
LTER_UNIT_DAYS,OpenSearchServer\Search\Field\Search::REL
ATIVE_DATE_FILTER_UNIT_HOURS andOpenSearchServer\Sear
ch\Field\Search::RELATIVE_DATE_FILTER_UNIT_MINUTES.
beOpenSearchServer\Search\Field\Search::RELATIVE_DATE_FI
LTER_UNIT_DAYS,OpenSearchServer\Search\Field\Search::REL
ATIVE_DATE_FILTER_UNIT_HOURS andOpenSearchServer\Sear
ch\Field\Search::RELATIVE_DATE_FILTER_UNIT_MINUTES.
is yyyyMMddHHmmss(OpenSearchServer\Search\Field\Searc
h::RELATIVE_DATE_FILTER_DATEFORMAT).
Parameters:
not.
Collapsing options
o collapsing(string $field, int $max, string $mode, string $type):
Join options
o join(string $indexName, string $queryTemplate, string $queryString,
string $localField, string $foreignField, string $type, boolean
$returnFields, boolean $returnScores, boolean $returnFacets):
Search(field)
Go to API documentation for this method
Fields that must be searched are specified precisely in this kind of query:
$request = new OpenSearchServer\Search\Field\Search();
$request->index('index_name')
...
//set some search fields
->searchFields(array('content', 'url'))
//set a specific different search field with Term & Phrase, term boost = 5 and
phrase boost = 10
->searchField('title',
OpenSearchServer\Search\Field\Search::SEARCH_MODE_TERM_AND_PHRASE, 5, 10)
...
$results = $oss_api->submit($request);
Available methods:
Search(pattern)
Go to API documentation for this method
With this kind of query searched fields are configured with a pattern language:
$request = new OpenSearchServer\Search\Pattern\Search();
$request->index('index_name')
...
//configure search pattern
->patternSearchQuery('title:($$)^10 OR titleExact:($$)^10 OR titlePhonetic:($
$)^10')
//configure pattern to use for snippets
->patternSnippetQuery('title:($$) OR content:($$)')
...
$results = $oss_api->submit($request);
Query template can be registered to be used later without having to give every
parameters. They can also be edited with the administration interface.
$request = new OpenSearchServer\Search\Pattern\Put();
$request->index('index_name')
->emptyReturnsAll()
->operator(OpenSearchServer\Search\Search::OPERATOR_AND)
->patternSearchQuery('title:($$)^10 OR titleExact:($$)^10 OR titlePhonetic:($
$)^10')
...
->template('template_name');
$results = $oss_api->submit($request);
Search templates
As shown above it is possible to save several search templates for future use.
->name('template_name');
$response = $oss_api->submit($request);
Synonyms
Create a list of synonyms
Go to API documentation for this method
$request = new OpenSearchServer\Synonyms\Create();
$request->index('index_name')
->name('hyperonyms')
->addSynonyms('couch,divan,sofa')
->addSynonyms(array(
'car,vehicle,transportation device',
'keyboard,electronic device'
));
$response = $oss_api->submit($request);
Available methods:
Available methods:
Available methods:
Available methods:
Available methods:
Filtering options
Parameters:
not.
Available methods:
Available methods:
Available methods:
Spellcheck queries
It is not possible at the moment to create Spellcheck query templates through API.
Spellcheck query templates can be listed, deleted and used for a search.
Scheduler
Get status of a scheduler job
Go to API documentation for this method
$request = new OpenSearchServer\Scheduler\GetStatus();
$request->index('index_name')
->name('test job');
$response = $oss_api->submit($request);
Available method:
Available method:
Replication
Get list of replications
Go to API documentation for this method
$request = new OpenSearchServer\Replication\GetList();
$request->index('articles');
$response = $oss_api->submit($request);
foreach($response as $key => $item) {
echo '<br/>Item #'.$key .': ';
var_dump($item);
}
Available method:
Available method:
Start a replication
Go to API documentation for this method
$request = new OpenSearchServer\Replication\Run();
$request->index('articles')
->name('http://localhost:9090/articles_test_repl');
$response = $oss_api->submit($request);
Available method:
Delete a replication
Go to API documentation for this method
$request = new OpenSearchServer\Replication\Delete();
$request->index('articles')
->name('http://localhost:9090/articles_test_repl');
$response = $oss_api->submit($request);
Available method: