Composing SearchConditions¶
In this chapter you will learn how to compose your SearchConditions, without using an input processor. Composing Conditions manually is perfect for testing your integration, or using RollerworksSearch as a SDK for (REST) APIs.
Creating a FieldSet¶
Before you can compose a SearchCondition you first need a FieldSet configuration, even when using the Condition only for exporting you need a FieldSet as the exporter needs to know which data transformer(s) to use.
A FieldSet is build using either the FieldSetBuilder or a FieldSetConfigurator, using a FieldSetConfigurator makes it possible for the FieldSet to be serialized and makes your configuration easily sharable for other processors.
For now we will use the FieldSetBuilder, building a FieldSet configuration for a user registration system.
Say your user registration system has the following columns (with the storage type):
user_id
: integerusername
: textpassword
: textfirst_name
: textlast_name
: textreg_date
: datetime
You want to allow searching in all columns except password, because RollerworksSearch is agnostic to your data system you need tell the system which fields there are and then later map these fields to a (table) column.
Note
It may feel redundant to map these fields twice, but this is with a reason.
A FieldSet can be used for any data system or storage, if the FieldSet was aware of your data system it would be only possible for one storage. And switching to ElasticSearch from Doctrine would be more difficult.
1 2 3 4 5 6 7 8 9 10 11 | use Rollerworks\Component\Search\Extension\Core\Type\TextType;
use Rollerworks\Component\Search\Extension\Core\Type\IntegerType;
use Rollerworks\Component\Search\Extension\Core\Type\DateTimeType;
$userFieldSet = $searchFactory->createFieldSetBuilder()
->add('id', IntegerType::class)
->add('username', TextType::class)
->add('firstName', TextType::class)
->add('lastName', TextType::class)
->add('regDate', DateTimeType::class)
->getFieldSet('users');
|
That’s it. The FieldSet is now ready for usage, the getFieldSet
method
has an optional argument where you can provide the name of the set (eg. users
).
Naming a set makes it easier to identify the set’s configuration when passed to a Condition processor. But it is not required for normal usage.
Tip
The getFieldSet
method produces a new FieldSet configuration every time,
this allows to create multiple FieldSet configurations who share a common
structure and configuration.
And now you can use the FieldSet for the SearchConditionBuilder, note that values must be provided in the “model” format of the field-type.
For the DateTimeType this is a DateTime
object, for the id this is an
integer
, and username is a string
.
For this example we want to search for users:
Registered between the years 2015 and 2016 (but not within the month May) or have a username which contains the word “admin”.
use Rollerworks\Component\Search\ConditionOptimizer\DuplicateRemover;
use Rollerworks\Component\Search\SearchConditionBuilder;
use Rollerworks\Component\Search\Test\SearchConditionOptimizerTestCase;
use Rollerworks\Component\Search\Value\Compare;
use Rollerworks\Component\Search\Value\ExcludedRange;
use Rollerworks\Component\Search\Value\PatternMatch;
use Rollerworks\Component\Search\Value\Range;
use Rollerworks\Component\Search\Value\ValuesBag;
use Rollerworks\Component\Search\Value\ValuesGroup;
$condition = SearchConditionBuilder::create($fieldSet, ValuesGroup::GROUP_LOGICAL_OR)
->field('regDate')
->add(new Range(new DateTime('2015-01-01 00:00:00 UTC'), new DateTime('2017-01-01 00:00:00 UTC'), true, false))
->add(new ExcludedRange(new DateTime('2015-03-01 00:00:00 UTC'), new DateTime('2015-04-01 00:00:00 UTC'), true, false))
end()
->field('name')
->add(new PatternMatch('admin', PatternMatch::PATTERN_CONTAINS))
->end()
->getSearchCondition();
Lets break this down, field('name')
tells the builder we want to work on
a SearchField named name
. Once we are done we call end
and return back to
the ValuesGroup were we can add/remove other fields, and add new/remove (sub)groups.
new Range(new DateTime('2015-01-01 00:00:00 UTC'), new DateTime('2017-01-01 00:00:00 UTC'), true, false)
This code segment creates a new Range
value value-holder with an inclusive
lower bound and exclusive upper bound (everything lower then the value itself).
Note
Calling field('name')
multiple times will return the same instance
of the ValuesBagBuilder
. Use field('name', true)
to overwrite
the existing instance.
The SearchConditionBuilder
is really powerful and developer friendly, but
instead of explaining everything, the following full example should give you an
idea about whats possible:
use Rollerworks\Component\Search\ConditionOptimizer\DuplicateRemover;
use Rollerworks\Component\Search\SearchConditionBuilder;
use Rollerworks\Component\Search\Test\SearchConditionOptimizerTestCase;
use Rollerworks\Component\Search\Value\Compare;
use Rollerworks\Component\Search\Value\ExcludedRange;
use Rollerworks\Component\Search\Value\PatternMatch;
use Rollerworks\Component\Search\Value\Range;
use Rollerworks\Component\Search\Value\ValuesBag;
use Rollerworks\Component\Search\Value\ValuesGroup;
$condition = SearchConditionBuilder::create($fieldSet, ValuesGroup::GROUP_LOGICAL_OR)
->field('regDate')
->add(new Range(new DateTime('2015-01-01 00:00:00 UTC'), new DateTime('2017-01-01 00:00:00 UTC'), true, false))
->add(new ExcludedRange(new DateTime('2015-03-01 00:00:00 UTC'), new DateTime('2015-04-01 00:00:00 UTC'), true, false))
end()
->field('name')
->add(new PatternMatch('admin', PatternMatch::PATTERN_CONTAINS))
->end()
->group()
->field('id')
->addSimpleValue(2)
->addSimpleValue(5)
->add(new Compare(10, '>'))
->end()
->group(ValuesGroup::GROUP_LOGICAL_OR)
->field('first-name')
->addSimpleValue('homer')
->add(new PatternMatch('spider', PatternMatch::PATTERN_CONTAINS))
->add(new PatternMatch('pig', PatternMatch::PATTERN_CONTAINS))
->add(new PatternMatch('doctor', PatternMatch::PATTERN_STARTS_WITH, true)) // case-insensitive match
->add(new PatternMatch('who', PatternMatch::PATTERN_CONTAINS, true)) // case-insensitive match
->end()
->end()
->end()
->getSearchCondition();
You can group as deep as needed, and always return to the previous level using end()
.
The builder support all of your complex and simple conditions.
See also SearchConditions in action
Further reading¶
Visual condition builder
(coming soon)- Exporting SearchConditions