Skip to content

Commit

Permalink
Create class and methods for performing search operation
Browse files Browse the repository at this point in the history
  • Loading branch information
foadyousefi committed Jan 31, 2019
1 parent 77e02cd commit e509041
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 32 deletions.
190 changes: 190 additions & 0 deletions lib/Query/Query.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

namespace FKRediSearch\RediSearch;

use InvalidArgumentException;

class Query {
protected $return = '';
protected $summarize = '';
protected $highlight = '';
protected $expander = '';
protected $payload = '';
protected $limit = '';
protected $slop = null;
protected $verbatim = '';
protected $withScores = '';
protected $withPayloads = '';
protected $noStopWords = '';
protected $noContent = '';
protected $inFields = '';
protected $inKeys = '';
protected $numericFilters = [];
protected $geoFilters = [];
protected $sortBy = '';
protected $scorer = '';
protected $language = '';
protected $client;
private $indexName;

public function __construct($client, $indexName) {
$this->client = $client;
$this->indexName = $indexName;
}

public function noContent() {
$this->noContent = 'NOCONTENT';
return $this;
}

public function return($fields) {
$count = empty( $fields ) ? 0 : count( $fields );
$field = implode(' ', $fields);
$this->return = "RETURN $count $field";
return $this;
}

public function summarize( $fields, $fragmentCount = 3, $fragmentLength = 50, $separator = '...') {
$count = empty($fields) ? 0 : count($fields);
$field = implode(' ', $fields);
$this->summarize = "SUMMARIZE FIELDS $count $field FRAGS $fragmentCount LEN $fragmentLength SEPARATOR $separator";
return $this;
}

public function highlight($fields, $openTag = '<strong>', $closeTag = '</strong>') {
$count = empty($fields) ? 0 : count($fields);
$field = implode(' ', $fields);
$this->highlight = "HIGHLIGHT FIELDS $count $field TAGS $openTag $closeTag";
return $this;
}

public function expander( $expander ) {
$this->expander = "EXPANDER $expander";
return $this;
}

public function payload( $payload) {
$this->payload = "PAYLOAD $payload";
return $this;
}

public function limit( $offset, $pageSize = 10) {
$this->limit = "LIMIT $offset $pageSize";
return $this;
}

public function inFields( $number, $fields) {
$this->inFields = "INFIELDS $number " . implode(' ', $fields);
return $this;
}

public function inKeys( $number, $keys) {
$this->inKeys = "INKEYS $number " . implode(' ', $keys);
return $this;
}

public function slop( $slop ) {
$this->slop = "SLOP $slop";
return $this;
}

public function noStopWords() {
$this->noStopWords = 'NOSTOPWORDS';
return $this;
}

public function withPayloads() {
$this->withPayloads = 'WITHPAYLOADS';
return $this;
}

public function withScores() {
$this->withScores = 'WITHSCORES';
return $this;
}

public function verbatim() {
$this->verbatim = 'VERBATIM';
return $this;
}

public function numericFilter( $fieldName, $min, $max = null ) {
$max = $max ?? '+inf';
$this->numericFilters[] = "@$fieldName:[$min $max]";
return $this;
}

public function geoFilter( $fieldName, $longitude, $latitude, $radius, $distanceUnit = 'km') {
$geo_units = array( 'm', 'km', 'mi', 'ft' );
if ( !in_array($distanceUnit, $geo_units) ) {
throw new InvalidArgumentException($distanceUnit);
}

$this->geoFilters[] = "@$fieldName:[$longitude $latitude $radius $distanceUnit]";
return $this;
}

public function sortBy( $fieldName, $order = 'ASC' ) {
$this->sortBy = "SORTBY $fieldName $order";
return $this;
}

public function scorer( $scoringFunction ) {
$this->scorer = "SCORER $scoringFunction";
return $this;
}

public function language( $languageName ) {
$this->language = "LANGUAGE $languageName";
return $this;
}

public function searchQueryArgs( $query ) {
$queryParts = array_merge([$query], $this->numericFilters, $this->geoFilters);
$queryWithFilters = "'" . implode(' ', $queryParts) . "'";
return array_filter(
array_merge(
trim($queryWithFilters) === '' ? [$this->indexName] : [$this->indexName, $queryWithFilters],
explode(' ', $this->limit),
explode(' ', $this->slop),
[
$this->verbatim,
$this->withScores,
$this->withPayloads,
$this->noStopWords,
$this->noContent,
],
explode(' ', $this->inFields),
explode(' ', $this->inKeys),
explode(' ', $this->return),
explode(' ', $this->summarize),
explode(' ', $this->highlight),
explode(' ', $this->sortBy),
explode(' ', $this->scorer),
explode(' ', $this->language),
explode(' ', $this->expander),
explode(' ', $this->payload)
),
function ($item) {
return !is_null($item) && $item !== '';
}
);
}

public function search( $query = '', $documentsAsArray = false ) {
$rawResult = $this->client->rawCommand( 'FT.SEARCH', $this->searchQueryArgs( $query ) );

return $rawResult ? SearchResult::searchResult(
$rawResult,
$documentsAsArray,
$this->withScores !== '',
$this->withPayloads !== '',
$this->noContent !== ''
) : new SearchResult(0, []);
}

public function explain( $query ) {
return $this->client->rawCommand( 'FT.EXPLAIN', $this->searchQueryArgs( $query ) );
}

}
74 changes: 74 additions & 0 deletions lib/Query/SearchResults.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
namespace FKRediSearch\RediSearch;

class SearchResult {
protected $count;
protected $documents;

public function __construct( $count, $documents ) {
$this->count = $count;
$this->documents = $documents;
}

public function getCount() {
return $this->count;
}

public function getDocuments() {
return $this->documents;
}

public static function searchResult( $rawRediSearchResult, $documentsAsArray, $withScores = false, $withPayloads = false, $noContent = false ) {
$docWidth = $noContent ? 1 : 2;
if ( !$rawRediSearchResult ) {
return false;
}

if ( count( $rawRediSearchResult ) === 1 ) {
return new SearchResult( 0, [] );
}

if ( $withScores ) {
$docWidth++;
}

if ( $withPayloads ) {
$docWidth++;
}

$count = array_shift( $rawRediSearchResult );
$documents = [];

for ($i = 0; $i < count( $rawRediSearchResult ); $i += $docWidth ) {
$document = $documentsAsArray ? [] : new \stdClass();
$documentsAsArray ?
$document['id'] = $rawRediSearchResult[$i] :
$document->id = $rawRediSearchResult[$i];

if ( $withScores ) {
$documentsAsArray ? $document['score'] = $rawRediSearchResult[ $i + 1 ] : $document->score = $rawRediSearchResult[ $i + 1 ];
}

if ($withPayloads) {
$j = $withScores ? 2 : 1;
$documentsAsArray ?
$document['payload'] = $rawRediSearchResult[$i+$j] :
$document->payload = $rawRediSearchResult[$i+$j];
}

if (!$noContent) {
$fields = $rawRediSearchResult[$i + ($docWidth - 1)];

if (is_array($fields)) {
for ($j = 0; $j < count($fields); $j += 2) {
$documentsAsArray ? $document[$fields[$j]] = $fields[$j + 1] : $document->{$fields[$j]} = $fields[$j + 1];
}
}
}

$documents[] = $document;
}

return new SearchResult($count, $documents);
}
}
30 changes: 0 additions & 30 deletions lib/Search.php

This file was deleted.

3 changes: 2 additions & 1 deletion vendor/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

return array(
'FKRediSearch\\RediSearch\\Index' => $baseDir . '/lib/Index.php',
'FKRediSearch\\RediSearch\\Search' => $baseDir . '/lib/Search.php',
'FKRediSearch\\RediSearch\\Query' => $baseDir . '/lib/Query/Query.php',
'FKRediSearch\\RediSearch\\SearchResult' => $baseDir . '/lib/Query/SearchResults.php',
'FKRediSearch\\RediSearch\\Setup' => $baseDir . '/lib/Setup.php',
'FKRediSearch\\RedisRaw\\AbstractRedisRawClient' => $baseDir . '/lib/RedisRaw/AbstractRedisRawClient.php',
'FKRediSearch\\RedisRaw\\PredisAdapter' => $baseDir . '/lib/RedisRaw/PredisAdapter.php',
Expand Down
3 changes: 2 additions & 1 deletion vendor/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class ComposerStaticInitfd524027e3158b3f967207bbbd1c5a01

public static $classMap = array (
'FKRediSearch\\RediSearch\\Index' => __DIR__ . '/../..' . '/lib/Index.php',
'FKRediSearch\\RediSearch\\Search' => __DIR__ . '/../..' . '/lib/Search.php',
'FKRediSearch\\RediSearch\\Query' => __DIR__ . '/../..' . '/lib/Query/Query.php',
'FKRediSearch\\RediSearch\\SearchResult' => __DIR__ . '/../..' . '/lib/Query/SearchResults.php',
'FKRediSearch\\RediSearch\\Setup' => __DIR__ . '/../..' . '/lib/Setup.php',
'FKRediSearch\\RedisRaw\\AbstractRedisRawClient' => __DIR__ . '/../..' . '/lib/RedisRaw/AbstractRedisRawClient.php',
'FKRediSearch\\RedisRaw\\PredisAdapter' => __DIR__ . '/../..' . '/lib/RedisRaw/PredisAdapter.php',
Expand Down

0 comments on commit e509041

Please sign in to comment.