Skip to content

Commit

Permalink
Left-inclusive only and right-inclusive only range queries (solariump…
Browse files Browse the repository at this point in the history
  • Loading branch information
thomascorthals authored Dec 25, 2020
1 parent 4547245 commit 2b4639e
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [unreleased]
### Added
- Extract query now supports extractFormat
- Helper::rangeQuery() now supports left-inclusive only and right-inclusive only queries

### Fixed

Expand Down
20 changes: 13 additions & 7 deletions src/Core/Query/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,32 +174,38 @@ public function formatDate($input)
* Example: rangeQuery('store', 5, null, false)
* Returns: store:{5 TO *}
*
* Example: rangeQuery('price', 0, 10, [true, false])
* Returns: price:[0 TO 10}
*
* @param string $field
* @param int|float|string|null $from
* @param int|float|string|null $to
* @param bool $inclusive TRUE if the the range should include the boundaries, FALSE otherwise
* @param bool|bool[] $inclusive TRUE or [TRUE, TRUE] for inclusive, FALSE or [FALSE, FALSE] for exclusive,
* [TRUE, FALSE] for left-inclusive only, [FALSE, TRUE] for right-inclusive only
*
* @return string
*/
public function rangeQuery(string $field, $from, $to, bool $inclusive = true): string
public function rangeQuery(string $field, $from, $to, $inclusive = true): string
{
if (null === $from) {
$from = '*';
} elseif (!is_int($from) && !is_float($from) && !Utility::isPointValue($from)) {
} elseif (!\is_int($from) && !\is_float($from) && !Utility::isPointValue($from)) {
$from = $this->escapePhrase($from);
}

if (null === $to) {
$to = '*';
} elseif (!is_int($to) && !is_float($to) && !Utility::isPointValue($to)) {
} elseif (!\is_int($to) && !\is_float($to) && !Utility::isPointValue($to)) {
$to = $this->escapePhrase($to);
}

if ($inclusive) {
return $field.':['.$from.' TO '.$to.']';
if (\is_array($inclusive)) {
list($leftInclusive, $rightInclusive) = $inclusive;
} else {
$leftInclusive = $rightInclusive = $inclusive;
}

return $field.':{'.$from.' TO '.$to.'}';
return sprintf('%s:%s%s TO %s%s', $field, $leftInclusive ? '[' : '{', $from, $to, $rightInclusive ? ']' : '}');
}

/**
Expand Down
159 changes: 157 additions & 2 deletions tests/Core/Query/HelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function setUp(): void
$this->helper = new Helper($this->query);
}

public function testRangeQueryInclusive()
public function testRangeQuery()
{
$this->assertEquals(
'field:[1 TO 2]',
Expand All @@ -43,6 +43,24 @@ public function testRangeQueryInclusive()
);
}

public function testRangeQueryInclusive()
{
$this->assertEquals(
'field:[1 TO 2]',
$this->helper->rangeQuery('field', 1, 2, true)
);

$this->assertSame(
'store:[45,-94 TO 46,-93]',
$this->helper->rangeQuery('store', '45,-94', '46,-93', true)
);

$this->assertEquals(
'field:["A" TO "M"]',
$this->helper->rangeQuery('field', 'A', 'M', true)
);
}

public function testRangeQueryExclusive()
{
$this->assertSame(
Expand All @@ -61,7 +79,79 @@ public function testRangeQueryExclusive()
);
}

public function testRangeQueryInclusiveNullValues()
public function testRangeQueryLeftInclusiveRightInclusive()
{
$this->assertEquals(
'field:[1 TO 2]',
$this->helper->rangeQuery('field', 1, 2, [true, true])
);

$this->assertSame(
'store:[45,-94 TO 46,-93]',
$this->helper->rangeQuery('store', '45,-94', '46,-93', [true, true])
);

$this->assertEquals(
'field:["A" TO "M"]',
$this->helper->rangeQuery('field', 'A', 'M', [true, true])
);
}

public function testRangeQueryLeftInclusiveRightExclusive()
{
$this->assertEquals(
'field:[1 TO 2}',
$this->helper->rangeQuery('field', 1, 2, [true, false])
);

$this->assertSame(
'store:[45,-94 TO 46,-93}',
$this->helper->rangeQuery('store', '45,-94', '46,-93', [true, false])
);

$this->assertEquals(
'field:["A" TO "M"}',
$this->helper->rangeQuery('field', 'A', 'M', [true, false])
);
}

public function testRangeQueryLeftExclusiveRightInclusive()
{
$this->assertEquals(
'field:{1 TO 2]',
$this->helper->rangeQuery('field', 1, 2, [false, true])
);

$this->assertSame(
'store:{45,-94 TO 46,-93]',
$this->helper->rangeQuery('store', '45,-94', '46,-93', [false, true])
);

$this->assertEquals(
'field:{"A" TO "M"]',
$this->helper->rangeQuery('field', 'A', 'M', [false, true])
);
}

public function testRangeQueryLeftExclusiveRightExclusive()
{
$this->assertEquals(
'field:{1 TO 2}',
$this->helper->rangeQuery('field', 1, 2, [false, false])
);

$this->assertSame(
'store:{45,-94 TO 46,-93}',
$this->helper->rangeQuery('store', '45,-94', '46,-93', [false, false])
);

$this->assertEquals(
'field:{"A" TO "M"}',
$this->helper->rangeQuery('field', 'A', 'M', [false, false])
);
}

public function testRangeQueryNullValues()
{
$this->assertSame(
'field:[1 TO *]',
Expand All @@ -74,6 +164,19 @@ public function testRangeQueryInclusiveNullValues()
);
}

public function testRangeQueryInclusiveNullValues()
{
$this->assertSame(
'field:[1 TO *]',
$this->helper->rangeQuery('field', 1, null, true)
);

$this->assertSame(
'store:[* TO 46,-93]',
$this->helper->rangeQuery('store', null, '46,-93', true)
);
}

public function testRangeQueryExclusiveNullValues()
{
$this->assertSame(
Expand All @@ -87,6 +190,58 @@ public function testRangeQueryExclusiveNullValues()
);
}

public function testRangeQueryLeftInclusiveRightInclusiveNullValues()
{
$this->assertSame(
'field:[1 TO *]',
$this->helper->rangeQuery('field', 1, null, [true, true])
);

$this->assertSame(
'store:[* TO 46,-93]',
$this->helper->rangeQuery('store', null, '46,-93', [true, true])
);
}

public function testRangeQueryLeftInclusiveRightExclusiveNullValues()
{
$this->assertSame(
'field:[1 TO *}',
$this->helper->rangeQuery('field', 1, null, [true, false])
);

$this->assertSame(
'store:[* TO 46,-93}',
$this->helper->rangeQuery('store', null, '46,-93', [true, false])
);
}

public function testRangeQueryLeftExclusiveRightInclusiveNullValues()
{
$this->assertSame(
'field:{1 TO *]',
$this->helper->rangeQuery('field', 1, null, [false, true])
);

$this->assertSame(
'store:{* TO 46,-93]',
$this->helper->rangeQuery('store', null, '46,-93', [false, true])
);
}

public function testRangeQueryLeftExclusiveRightExclusiveNullValues()
{
$this->assertSame(
'field:{1 TO *}',
$this->helper->rangeQuery('field', 1, null, [false, false])
);

$this->assertSame(
'store:{* TO 46,-93}',
$this->helper->rangeQuery('store', null, '46,-93', [false, false])
);
}

public function testGeofilt()
{
$this->assertSame(
Expand Down
67 changes: 67 additions & 0 deletions tests/Integration/AbstractTechproductsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,73 @@ public function testRangeQueries()
$result = self::$client->select($select);
$this->assertSame(14, $result->getNumFound());
$this->assertCount(10, $result);

// VS1GB400C3 costs 74.99, SP2514N costs 92.0, 0579B002 costs 179.99
$select->setFields('id,price');
$select->addSort('price', $select::SORT_ASC);
$select->setQuery(
$select->getHelper()->rangeQuery('price', 74.99, 179.99, [true, true])
);
$result = self::$client->select($select);
$this->assertSame(3, $result->getNumFound());
$iterator = $result->getIterator();
$this->assertSame([
'id' => 'VS1GB400C3',
'price' => 74.99,
], $iterator->current()->getFields());
$iterator->next();
$this->assertSame([
'id' => 'SP2514N',
'price' => 92.0,
], $iterator->current()->getFields());
$iterator->next();
$this->assertSame([
'id' => '0579B002',
'price' => 179.99,
], $iterator->current()->getFields());

$select->setQuery(
$select->getHelper()->rangeQuery('price', 74.99, 179.99, [true, false])
);
$result = self::$client->select($select);
$this->assertSame(2, $result->getNumFound());
$iterator = $result->getIterator();
$this->assertSame([
'id' => 'VS1GB400C3',
'price' => 74.99,
], $iterator->current()->getFields());
$iterator->next();
$this->assertSame([
'id' => 'SP2514N',
'price' => 92.0,
], $iterator->current()->getFields());

$select->setQuery(
$select->getHelper()->rangeQuery('price', 74.99, 179.99, [false, true])
);
$result = self::$client->select($select);
$this->assertSame(2, $result->getNumFound());
$iterator = $result->getIterator();
$this->assertSame([
'id' => 'SP2514N',
'price' => 92.0,
], $iterator->current()->getFields());
$iterator->next();
$this->assertSame([
'id' => '0579B002',
'price' => 179.99,
], $iterator->current()->getFields());

$select->setQuery(
$select->getHelper()->rangeQuery('price', 74.99, 179.99, [false, false])
);
$result = self::$client->select($select);
$this->assertSame(1, $result->getNumFound());
$iterator = $result->getIterator();
$this->assertSame([
'id' => 'SP2514N',
'price' => 92.0,
], $iterator->current()->getFields());
}

public function testFacetHighlightSpellcheckComponent()
Expand Down
5 changes: 4 additions & 1 deletion tests/Support/UtilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public function testIsPointValue()
$this->assertTrue(Utility::isPointValue($value));
}

$this->assertFalse(Utility::isPointValue('not a point value'));
$values = ['45', '-93', '45.15', '-93.85', '', 'not a point value'];
foreach ($values as $value) {
$this->assertFalse(Utility::isPointValue($value));
}
}
}

0 comments on commit 2b4639e

Please sign in to comment.