diff --git a/.github/workflows/03-phpunit.yml b/.github/workflows/03-phpunit.yml
index 960e51e..a97bafc 100644
--- a/.github/workflows/03-phpunit.yml
+++ b/.github/workflows/03-phpunit.yml
@@ -166,3 +166,29 @@ jobs:
- name: Run PHPUnit Tests
run: ./vendor/bin/phpunit --testsuite=mysql
+ meilisearch-storage:
+ runs-on: ubuntu-latest
+ services:
+ meilisearch:
+ image: getmeili/meilisearch:latest
+ options: >-
+ --health-cmd "curl -s http://localhost:7700/ -o /dev/null"
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ - "7700:7700"
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set up PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
+
+ - name: Install Composer Dependencies
+ run: composer install
+
+ - name: Run PHPUnit Tests
+ run: ./vendor/bin/phpunit --testsuite=meilisearch
diff --git a/composer.json b/composer.json
index d1ab941..b7f7b67 100644
--- a/composer.json
+++ b/composer.json
@@ -31,12 +31,21 @@
"opensearch-project/opensearch-php": "^2.0",
"shyim/opensearch-php-dsl": "^1.0.1",
"async-aws/dynamo-db": "^2.0",
- "mongodb/mongodb": "^1.16"
+ "mongodb/mongodb": "^1.16",
+ "meilisearch/meilisearch-php": "^1.5",
+ "symfony/http-client": "^6.4",
+ "nyholm/psr7": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^10.5",
"symfony/var-dumper": "^6.3",
"phpstan/phpstan": "^1.10",
- "friendsofphp/php-cs-fixer": "^3.35"
+ "friendsofphp/php-cs-fixer": "^3.35",
+ "kubawerlos/php-cs-fixer-custom-fixers": "~v3.14.0"
+ },
+ "config": {
+ "allow-plugins": {
+ "php-http/discovery": true
+ }
}
}
diff --git a/devenv.lock b/devenv.lock
index 566c143..d34a272 100644
--- a/devenv.lock
+++ b/devenv.lock
@@ -3,11 +3,11 @@
"devenv": {
"locked": {
"dir": "src/modules",
- "lastModified": 1696344641,
- "narHash": "sha256-cfGsdtDvzYaFA7oGWSgcd1yST6LFwvjMcHvtVj56VcU=",
+ "lastModified": 1704835383,
+ "narHash": "sha256-SoC0rYR9iHW0dVOEmxNEfa8vk9dTK86P5iXTgHafmwM=",
"owner": "cachix",
"repo": "devenv",
- "rev": "05e26941f34486bff6ebeb4b9c169b6f637f1758",
+ "rev": "18ef9849d1ecac7a9a7920eb4f2e4adcf67a8c3a",
"type": "github"
},
"original": {
@@ -74,11 +74,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1696419054,
- "narHash": "sha256-EdR+dIKCfqL3voZUDYwcvgRDOektQB9KbhBVcE0/3Mo=",
+ "lastModified": 1704842529,
+ "narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "7131f3c223a2d799568e4b278380cd9dac2b8579",
+ "rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5",
"type": "github"
},
"original": {
@@ -115,11 +115,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
- "lastModified": 1696158581,
- "narHash": "sha256-h0vY4E7Lx95lpYQbG2w4QH4yG5wCYOvPJzK93wVQbT0=",
+ "lastModified": 1705056064,
+ "narHash": "sha256-pi9UtBFD5/U48Jrc6uvA8ZCmW4xnceUDp2QysBEkZCw=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
- "rev": "033453f85064ccac434dfd957f95d8457901ecd6",
+ "rev": "54d60d191aa8ba0629f662d8873a892cbe3d65ad",
"type": "github"
},
"original": {
diff --git a/devenv.nix b/devenv.nix
index d2b4326..fd239ee 100644
--- a/devenv.nix
+++ b/devenv.nix
@@ -10,6 +10,7 @@
services.redis.enable = lib.mkDefault true;
services.adminer.enable = lib.mkDefault true;
services.adminer.listen = lib.mkDefault "127.0.0.1:9080";
+ services.meilisearch.enable = lib.mkDefault true;
languages.php = {
enable = lib.mkDefault true;
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index d607e92..76a6958 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -11,6 +11,7 @@
tests/Common
+
tests/Array
@@ -31,6 +32,10 @@
tests/Opensearch
+
+ tests/Meilisearch
+
+
tests/Redis
diff --git a/src/Meilisearch/MeilisearchStorage.php b/src/Meilisearch/MeilisearchStorage.php
new file mode 100644
index 0000000..2d36420
--- /dev/null
+++ b/src/Meilisearch/MeilisearchStorage.php
@@ -0,0 +1,312 @@
+paging instanceof Page) {
+ $params['page'] = $criteria->paging->page;
+ $params['hitsPerPage'] = $criteria->limit;
+ } elseif ($criteria->limit !== null) {
+ $params['limit'] = $criteria->limit;
+ }
+
+ $filters = $criteria->filters;
+ if ($criteria->keys !== null) {
+ $filters[] = new Any(field: 'key', value: $criteria->keys);
+ }
+
+ if (!empty($filters)) {
+ $params['filter'] = $this->parse($filters, $context);
+ }
+
+ $result = $this->index()->search(
+ query: null,
+ searchParams: $params
+ );
+
+ $documents = [];
+ foreach ($result->getHits() as $hit) {
+ $key = $hit['key'];
+ unset($hit['key']);
+
+ $documents[] = new Document(key: $key, data: $hit);
+ }
+
+ return new FilterResult(
+ elements: $documents
+ );
+ }
+
+ public function remove(array $keys): void
+ {
+ $this->index()->deleteDocuments($keys);
+ }
+
+ public function store(Documents $documents): void
+ {
+ $data = [];
+ foreach ($documents as $document) {
+ $record = $document->data;
+ $record['key'] = $document->key;
+ $data[] = $record;
+ }
+
+ $this->index()->addDocuments($data);
+ }
+
+ public function setup(): void {}
+
+ public function index(): Indexes
+ {
+ return $this->client->index($this->schema->source);
+ }
+
+ /**
+ * @param array $filters
+ */
+ private function parse(array $filters, StorageContext $context): string
+ {
+ $parsed = [];
+
+ foreach ($filters as $filter) {
+ if ($filter instanceof Operator) {
+ $parsed[] = $this->parseOperator($filter, $context);
+ }
+
+ if ($filter instanceof Filter) {
+ $parsed[] = $this->parseFilter($filter, $context);
+ }
+ }
+
+ if (count($parsed) === 1) {
+ return $parsed[0];
+ }
+
+ return self::and($parsed);
+ }
+
+ private static function cast(mixed $value): mixed
+ {
+ if (is_string($value)) {
+ return '"' . $value . '"';
+ }
+
+ if (is_bool($value)) {
+ return $value ? 'true' : 'false';
+ }
+
+ if (!is_array($value)) {
+ return $value;
+ }
+
+ return array_map(fn($v) => self::cast($v), $value);
+ }
+
+ private function parseFilter(Filter $filter, StorageContext $context): string
+ {
+ $property = SchemaUtil::property($filter->field);
+
+ $translated = SchemaUtil::translated(schema: $this->schema, accessor: $property);
+
+ $value = SchemaUtil::cast($this->schema, $filter->field, $filter->value);
+
+ $value = self::cast($value);
+
+ $factory = function (\Closure $closure) use ($filter, $value) {
+ return $closure($filter->field, $value);
+ };
+
+ if ($translated) {
+ $factory = function (\Closure $closure) use ($filter, $context, $value) {
+ return $this->translatedQuery($closure, $filter, $value, $context);
+ };
+ }
+
+ if (is_string($filter->value) && ($filter instanceof Lt || $filter instanceof Gt || $filter instanceof Lte || $filter instanceof Gte)) {
+ throw new NotSupportedByEngine('34', 'Meilisearch does not support string comparison.');
+ }
+ if ($filter instanceof Contains) {
+ throw new NotSupportedByEngine('33', ' Meilisearch contains/prefix/suffix filter are not supported.');
+ }
+ if ($filter instanceof Prefix) {
+ throw new NotSupportedByEngine('33', ' Meilisearch contains/prefix/suffix filter are not supported.');
+ }
+ if ($filter instanceof Suffix) {
+ throw new NotSupportedByEngine('33', ' Meilisearch contains/prefix/suffix filter are not supported.');
+ }
+
+ if ($filter->value === null) {
+ if ($filter instanceof Equals) {
+ return $factory(fn($field, $value) => $field . ' IS NULL');
+ }
+
+ if ($filter instanceof Not) {
+ return $factory(fn($field, $value) => $field . ' IS NOT NULL');
+ }
+
+ throw new \RuntimeException('Null filter values are only supported for Equals and Not filters');
+ }
+
+ if ($filter instanceof Equals) {
+ return $factory(fn($field, $value) => $field . ' = ' . $value);
+ }
+
+ if ($filter instanceof Not) {
+ return $factory(fn($field, $value) => $field . ' != ' . $value);
+ }
+
+ if ($filter instanceof Any) {
+ return $factory(function (string $field, mixed $value) {
+ return $field . ' IN [' . implode(',', $value) . ']';
+ });
+ }
+
+ if ($filter instanceof Neither) {
+
+ return $factory(function (string $field, mixed $value) {
+ return $field . ' NOT IN [' . implode(',', $value) . ']';
+ });
+ }
+
+ if ($filter instanceof Lt) {
+ return $factory(fn($field, $value) => $field . ' < ' . $value);
+ }
+
+ if ($filter instanceof Gt) {
+ return $factory(fn($field, $value) => $field . ' > ' . $value);
+ }
+
+ if ($filter instanceof Lte) {
+ return $factory(fn($field, $value) => $field . ' <= ' . $value);
+ }
+
+ if ($filter instanceof Gte) {
+ return $factory(fn($field, $value) => $field . ' >= ' . $value);
+ }
+
+ throw new \RuntimeException('Unknown filter: ' . get_class($filter));
+ }
+
+ private function parseOperator(Operator $operator, StorageContext $context): string
+ {
+ $parsed = [];
+ foreach ($operator->filters as $filter) {
+ $parsed[] = $this->parse([$filter], $context);
+ }
+
+ if ($operator instanceof AndOperator) {
+ return self::and($parsed);
+ }
+
+ if ($operator instanceof OrOperator) {
+ return self::or($parsed);
+ }
+
+ if ($operator instanceof NandOperator) {
+ return 'NOT ' . self::and($parsed);
+ }
+
+ if ($operator instanceof NorOperator) {
+ return 'NOT ' . self::or($parsed);
+ }
+
+ throw new \RuntimeException('Unknown operator: ' . get_class($operator));
+ }
+
+ private function translatedQuery(\Closure $closure, Filter $filter, mixed $value, StorageContext $context): string
+ {
+ $queries = [];
+
+ $before = [];
+
+ foreach ($context->languages as $index => $languageId) {
+ if (array_key_first($context->languages) === $index) {
+ $queries[] = self::and([
+ $filter->field . '.' . $languageId . ' EXISTS',
+ $filter->field . '.' . $languageId . ' IS NOT NULL',
+ $closure($filter->field . '.' . $languageId, $value),
+ ]);
+
+ $before[] = $languageId;
+
+ continue;
+ }
+
+ $nested = [];
+ foreach ($before as $id) {
+ $nested[] = self::or([
+ $filter->field . '.' . $id . ' NOT EXISTS',
+ $filter->field . '.' . $id . ' IS NULL'
+ ]);
+ }
+
+ $nested[] = self::and([
+ $filter->field . '.' . $languageId . ' EXISTS',
+ $filter->field . '.' . $languageId . ' IS NOT NULL',
+ $closure($filter->field . '.' . $languageId, $value),
+ ]);
+
+ $before[] = $languageId;
+
+ $queries[] = self::and($nested);
+ }
+
+ return self::or($queries);
+ }
+
+ /**
+ * @param array $elements
+ */
+ private static function or(array $elements): string
+ {
+ return '(' . implode(' OR ', $elements) . ')';
+ }
+
+ /**
+ * @param array $elements
+ */
+ private static function and(array $elements): string
+ {
+ return '(' . implode(' AND ', $elements) . ')';
+ }
+}
diff --git a/src/Meilisearch/composer.json b/src/Meilisearch/composer.json
new file mode 100644
index 0000000..0b06738
--- /dev/null
+++ b/src/Meilisearch/composer.json
@@ -0,0 +1,3 @@
+{
+ "name": "shopware/storage-meilisearch"
+}
\ No newline at end of file
diff --git a/tests/Meilisearch/LiveMeilisearchStorage.php b/tests/Meilisearch/LiveMeilisearchStorage.php
new file mode 100644
index 0000000..6343510
--- /dev/null
+++ b/tests/Meilisearch/LiveMeilisearchStorage.php
@@ -0,0 +1,57 @@
+storage->filter($criteria, $context);
+ }
+
+ public function remove(array $keys): void
+ {
+ $this->storage->remove($keys);
+
+ $this->wait();
+ }
+
+ public function store(Documents $documents): void
+ {
+ $this->storage->store($documents);
+
+ $this->wait();
+ }
+
+ public function setup(): void {}
+
+ private function wait(): void
+ {
+ $tasks = new TasksQuery();
+ $tasks->setStatuses(['enqueued', 'processing']);
+
+ $tasks = $this->client->getTasks($tasks);
+
+ $ids = array_map(fn($task) => $task['uid'], $tasks->getResults());
+
+ if (count($ids) === 0) {
+ return;
+ }
+
+ $this->client->waitForTasks($ids);
+ }
+}
diff --git a/tests/Meilisearch/MeilisearchStorageTest.php b/tests/Meilisearch/MeilisearchStorageTest.php
new file mode 100644
index 0000000..fe4715a
--- /dev/null
+++ b/tests/Meilisearch/MeilisearchStorageTest.php
@@ -0,0 +1,2350 @@
+getClient()->getIndex($this->getSchema()->source);
+ } catch (ApiException) {
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ if ($this->exists()) {
+ $this->index()->deleteAllDocuments();
+
+ $this->wait();
+
+ return;
+ }
+
+ $this->getClient()->deleteIndex($this->getSchema()->source);
+
+ $this->wait();
+
+ $this->getClient()->createIndex(
+ uid: $this->getSchema()->source,
+ options: ['primaryKey' => 'key']
+ );
+
+ $fields = array_map(fn($field) => $field->name, $this->getSchema()->fields);
+
+ $fields[] = 'key';
+
+ $fields = array_values(array_filter($fields));
+
+ $this->index()
+ ->updateFilterableAttributes($fields);
+
+ $this->index()
+ ->updateSortableAttributes($fields);
+
+ $this->wait();
+ }
+
+ #[DataProvider('debugProvider')]
+ public function testDebug(
+ Documents $input,
+ FilterCriteria $criteria,
+ FilterResult $expected
+ ): void {
+ $storage = $this->getStorage();
+
+ $storage->store($input);
+
+ try {
+ $loaded = $storage->filter($criteria, new StorageContext(languages: ['en', 'de']));
+ } catch (NotSupportedByEngine $e) {
+ static::markTestIncomplete($e->getMessage());
+ }
+
+ static::assertEquals($expected, $loaded);
+ }
+
+ public static function debugProvider(): \Generator
+ {
+ yield 'Test object field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ ])
+ ];
+ yield 'Test object field equals any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectField.foo', value: ['baz', 'qux'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ])
+ ];
+ yield 'Test object field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ])
+ ];
+ yield 'Test object field not any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'objectField.foo', value: ['baz', 'qux'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ ])
+ ];
+ yield 'Test object field contains filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'objectField.foo', value: 'ba')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ ])
+ ];
+ yield 'Test object field gte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ])
+ ];
+ yield 'Test object field lte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ ])
+ ];
+ yield 'Test object field gt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ])
+ ];
+ yield 'Test object field lt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ self::document(key: 'key2', objectField: ['foo' => 'baz']),
+ self::document(key: 'key3', objectField: ['foo' => 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['foo' => 'bar']),
+ ])
+ ];
+
+ yield 'Test object field equals filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ ])
+ ];
+ yield 'Test object field equals any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectField.fooInt', value: [1, 2])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ ])
+ ];
+ yield 'Test object field not filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ])
+ ];
+ yield 'Test object field not any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'objectField.fooInt', value: [1, 2])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ])
+ ];
+ yield 'Test object field gte filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ])
+ ];
+ yield 'Test object field lte filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ ])
+ ];
+ yield 'Test object field gt filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ])
+ ];
+ yield 'Test object field lt filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ ])
+ ];
+ yield 'Test object field gte and lte filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooInt' => 1]),
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ self::document(key: 'key4', objectField: ['fooInt' => 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooInt', value: 2),
+ new Lte(field: 'objectField.fooInt', value: 3),
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooInt' => 2]),
+ self::document(key: 'key3', objectField: ['fooInt' => 3]),
+ ])
+ ];
+
+ yield 'Test object field equals filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ ])
+ ];
+ yield 'Test object field equals any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectField.fooFloat', value: [1.1, 2.2])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ ])
+ ];
+ yield 'Test object field not filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ])
+ ];
+ yield 'Test object field not any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'objectField.fooFloat', value: [1.1, 2.2])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ])
+ ];
+ yield 'Test object field gte filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ])
+ ];
+ yield 'Test object field lte filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ ])
+ ];
+ yield 'Test object field gt filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ])
+ ];
+ yield 'Test object field lt filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ ])
+ ];
+ yield 'Test object field gte and lte filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooFloat' => 1.1]),
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ self::document(key: 'key4', objectField: ['fooFloat' => 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooFloat', value: 2.2),
+ new Lte(field: 'objectField.fooFloat', value: 3.3),
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooFloat' => 2.2]),
+ self::document(key: 'key3', objectField: ['fooFloat' => 3.3]),
+ ])
+ ];
+
+ yield 'Test object field equals filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field equals any filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectField.fooDate', value: ['2021-01-02', '2021-01-03'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field not filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field not any filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'objectField.fooDate', value: ['2021-01-02', '2021-01-03'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field gte filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field lte filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field gt filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field lt filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectField.fooDate', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ ])
+ ];
+ yield 'Test object field gte and lte filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooDate' => '2021-01-01 00:00:00.000']),
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key4', objectField: ['fooDate' => '2021-01-04 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectField.fooDate', value: '2021-01-02'),
+ new Lte(field: 'objectField.fooDate', value: '2021-01-03'),
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooDate' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', objectField: ['fooDate' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+
+ yield 'Test list field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'listField', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ ])
+ ];
+ yield 'Test list field equals any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'listField', value: ['baz', 'qux'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ])
+ ];
+ yield 'Test list field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'listField', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ])
+ ];
+ yield 'Test list field not any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'listField', value: ['baz', 'qux'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ ])
+ ];
+ yield 'Test list field contains filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ self::document(key: 'key3', listField: ['foo', 'qux']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'listField', value: 'ba')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['foo', 'bar']),
+ self::document(key: 'key2', listField: ['foo', 'baz']),
+ ])
+ ];
+ yield 'Test list field null value equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: null),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'listField', value: null)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', listField: null)
+ ])
+ ];
+ yield 'Test list field null value not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: null),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'listField', value: null)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document('key1', listField: [1, 2]),
+ self::document('key2', listField: [1, 3])
+ ])
+ ];
+
+ yield 'Test list field equals filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'listField', value: 3)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: [1, 3]),
+ ])
+ ];
+ yield 'Test list field equals any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'listField', value: [3, 4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ])
+ ];
+ yield 'Test list field not filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'listField', value: 3)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ])
+ ];
+ yield 'Test list field not any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1, 2]),
+ self::document(key: 'key2', listField: [1, 3]),
+ self::document(key: 'key3', listField: [1, 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'listField', value: [3, 4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: [1, 2]),
+ ])
+ ];
+ yield 'Test list field equals filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'listField', value: 3.3)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ ])
+ ];
+ yield 'Test list field equals any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'listField', value: [3.3, 4.4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ])
+ ];
+ yield 'Test list field not filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'listField', value: 3.3)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ])
+ ];
+ yield 'Test list field not any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ self::document(key: 'key2', listField: [1.1, 3.3]),
+ self::document(key: 'key3', listField: [1.1, 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'listField', value: [3.3, 4.4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: [1.1, 2.2]),
+ ])
+ ];
+ yield 'Test list field equals filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'listField', value: '2021-01-03')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ ])
+ ];
+ yield 'Test list field equals any filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'listField', value: ['2021-01-03', '2021-01-04'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ])
+ ];
+ yield 'Test list field not filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'listField', value: '2021-01-03')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ])
+ ];
+ yield 'Test list field not any filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'listField', value: ['2021-01-03', '2021-01-04'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ ])
+ ];
+ yield 'Test list field contains filter and date values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ self::document(key: 'key2', listField: ['2021-01-01', '2021-01-03']),
+ self::document(key: 'key3', listField: ['2021-01-01', '2021-01-04']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'listField', value: '2021-01-02')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', listField: ['2021-01-01', '2021-01-02']),
+ ])
+ ];
+
+ yield 'Test list object field equals filter and string value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectListField.foo', value: 'baz-2')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ])
+ ];
+ yield 'Test list object field equals any filter and string value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectListField.foo', value: ['bar-2', 'qux-2'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ])
+ ];
+ yield 'Test list object field contains filter and string value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'objectListField.foo', value: 'baz')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ])
+ ];
+ yield 'Test list object field starts-with filter and string value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Prefix(field: 'objectListField.foo', value: 'qu')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ])
+ ];
+ yield 'Test list object field ends-with filter and string value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['foo' => 'bar'], ['foo' => 'bar-2']]),
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Suffix(field: 'objectListField.foo', value: 'z-2')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['foo' => 'baz'], ['foo' => 'baz-2']]),
+ self::document(key: 'key3', objectListField: [['foo' => 'qux'], ['foo' => 'qux-2'], ['foo' => 'baz-2']]),
+ ])
+ ];
+
+ yield 'Test list object field equals filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectListField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ ])
+ ];
+ yield 'Test list object field equals any filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectListField.fooInt', value: [10, 22])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ])
+ ];
+ yield 'Test list object field gte filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectListField.fooInt', value: 22)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ])
+ ];
+ yield 'Test list object field lte filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectListField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ ])
+ ];
+ yield 'Test list object field gt filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectListField.fooInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ])
+ ];
+ yield 'Test list object field lt filter and int value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ self::document(key: 'key3', objectListField: [['fooInt' => 20], ['fooInt' => 22], ['fooInt' => 24]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectListField.fooInt', value: 20)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooInt' => 1], ['fooInt' => 2]]),
+ self::document(key: 'key2', objectListField: [['fooInt' => 10], ['fooInt' => 2]]),
+ ])
+ ];
+
+ yield 'Test list object field equals filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectListField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ ])
+ ];
+ yield 'Test list object field equals any filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectListField.fooFloat', value: [10.1, 22.2])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ])
+ ];
+ yield 'Test list object field gte filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectListField.fooFloat', value: 22.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ])
+ ];
+
+ yield 'Test list object field lte filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectListField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ ])
+ ];
+ yield 'Test list object field gt filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectListField.fooFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ])
+ ];
+ yield 'Test list object field lt filter and float value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key3', objectListField: [['fooFloat' => 20.1], ['fooFloat' => 22.2], ['fooFloat' => 24.2]]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectListField.fooFloat', value: 20.1)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooFloat' => 1.1], ['fooFloat' => 2.2]]),
+ self::document(key: 'key2', objectListField: [['fooFloat' => 10.1], ['fooFloat' => 2.2]]),
+ ])
+ ];
+
+ yield 'Test list object field equals filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectListField.fooDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ ])
+ ];
+ yield 'Test list object field equals any filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'objectListField.fooDate', value: ['2021-01-10 00:00:00.000', '2021-01-22 00:00:00.000'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ])
+ ];
+
+ yield 'Test list object field gte filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'objectListField.fooDate', value: '2021-01-22 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ])
+ ];
+ yield 'Test list object field lte filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'objectListField.fooDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ ])
+ ];
+ yield 'Test list object field gt filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'objectListField.fooDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ])
+ ];
+ yield 'Test list object field lt filter and date value' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key3', objectListField: [['fooDate' => '2021-01-20 00:00:00.000'], ['fooDate' => '2021-01-22 00:00:00.000'], ['fooDate' => '2021-01-24 00:00:00.000']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'objectListField.fooDate', value: '2021-01-20 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', objectListField: [['fooDate' => '2021-01-01 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ self::document(key: 'key2', objectListField: [['fooDate' => '2021-01-10 00:00:00.000'], ['fooDate' => '2021-01-02 00:00:00.000']]),
+ ])
+ ];
+
+ yield 'Test nested object' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', objectField: ['fooObj' => ['bar' => 'baz']]),
+ self::document(key: 'key2', objectField: ['fooObj' => ['bar' => 'qux']]),
+ self::document(key: 'key3', objectField: ['fooObj' => ['bar' => 'quux']]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'objectField.fooObj.bar', value: 'qux')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', objectField: ['fooObj' => ['bar' => 'qux']]),
+ ])
+ ];
+
+ yield 'Test translated string field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedString', value: 'foo')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field equals-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedString', value: ['foo', 'bar'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedString', value: 'foo')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field not any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedString', value: ['foo', 'bar'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field contains filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'boo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'translatedString', value: 'oo')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'boo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ ])
+ ];
+ yield 'Test translated string field starts-with filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'baz', 'de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Prefix(field: 'translatedString', value: 'foo')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field ends-with filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['en' => 'ob', 'de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Suffix(field: 'translatedString', value: 'o')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'foo']),
+ ])
+ ];
+ yield 'Test translated string field gte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'translatedString', value: 'b')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ])
+ ];
+ yield 'Test translated string field gt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'translatedString', value: 'b')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ ])
+ ];
+ yield 'Test translated string field lte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'translatedString', value: 'b')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ])
+ ];
+ yield 'Test translated string field lt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ self::document(key: 'key2', translatedString: ['en' => 'c']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'b']),
+ self::document(key: 'key4', translatedString: ['en' => 'b', 'de' => 'a']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'translatedString', value: 'b')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedString: ['en' => 'a', 'de' => 'b']),
+ ])
+ ];
+ yield 'Test translated string field equals filter and empty string' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'bar', 'de' => 'foo']),
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key3', translatedString: ['en' => '', 'de' => 'foo']),
+ self::document(key: 'key4', translatedString: ['de' => 'foo']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedString', value: 'foo')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'foo']),
+ self::document(key: 'key4', translatedString: ['de' => 'foo']),
+ ])
+ ];
+
+ yield 'Test translated int field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ])
+ ];
+ yield 'Test translated int field equals-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 3]),
+ self::document(key: 'key4', translatedInt: ['de' => 4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedInt', value: [2, 3, 4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 3]),
+ self::document(key: 'key4', translatedInt: ['de' => 4]),
+ ])
+ ];
+ yield 'Test translated int field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ ])
+ ];
+ yield 'Test translated int field not-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedInt', value: [1, 2])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+ yield 'Test translated int field gte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ ])
+ ];
+ yield 'Test translated int field gt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ ])
+ ];
+ yield 'Test translated int field lte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ])
+ ];
+ yield 'Test translated int field lt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 3]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 1]),
+ ])
+ ];
+
+ yield 'Test translated float field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated float field equals-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 3.3]),
+ self::document(key: 'key4', translatedFloat: ['de' => 4.4]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedFloat', value: [2.2, 3.3, 4.4])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 3.3]),
+ self::document(key: 'key4', translatedFloat: ['de' => 4.4]),
+ ])
+ ];
+ yield 'Test translated float field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated float field not-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedFloat', value: [1.1, 2.2])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+ yield 'Test translated float field gte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated float field gt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ ])
+ ];
+ yield 'Test translated float field lte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ])
+ ];
+ yield 'Test translated float field lt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 3.3]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 1.1]),
+ ])
+ ];
+
+ yield 'Test translated bool field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedBool', value: false)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ])
+ ];
+ yield 'Test translated bool field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedBool', value: false)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ ])
+ ];
+
+ yield 'Test translated date field equals filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field equals-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedDate', value: ['2021-01-02 00:00:00.000', '2021-01-03 00:00:00.000'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field not filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field not-any filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-02 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedDate', value: ['2021-01-01 00:00:00.000', '2021-01-02 00:00:00.000'])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+ yield 'Test translated date field gte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gte(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field gt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Gt(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field lte filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lte(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ])
+ ];
+ yield 'Test translated date field lt filter' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key2', translatedDate: ['en' => '2021-01-03 00:00:00.000']),
+ self::document(key: 'key3', translatedDate: ['en' => null, 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Lt(field: 'translatedDate', value: '2021-01-02 00:00:00.000')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedDate: ['en' => '2021-01-01 00:00:00.000', 'de' => '2021-01-02 00:00:00.000']),
+ self::document(key: 'key4', translatedDate: ['de' => '2021-01-01 00:00:00.000']),
+ ])
+ ];
+
+ yield 'Test translated list field equals filter and string values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedString', value: 'bar')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ])
+ ];
+ yield 'Test translated list field equals-any filter and string values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'baz']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedString', value: ['bar', 'baz'])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'baz']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ])
+ ];
+ yield 'Test translated list field not filter and string values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedString', value: 'bar')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ ])
+ ];
+ yield 'Test translated list field not-any filter and string values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedString', value: ['foo', 'bar'])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+ yield 'Test translated list field contains filter and string values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedString: ['en' => 'foo', 'de' => 'bar']),
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Contains(field: 'translatedString', value: 'ba')
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedString: ['en' => 'bar']),
+ self::document(key: 'key3', translatedString: ['en' => null, 'de' => 'bar']),
+ self::document(key: 'key4', translatedString: ['de' => 'bar']),
+ ])
+ ];
+
+ yield 'Test translated list field equals filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ])
+ ];
+ yield 'Test translated list field equals-any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 3]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedInt', value: [2, 3])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 3]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ])
+ ];
+ yield 'Test translated list field not filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedInt', value: 2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ ])
+ ];
+ yield 'Test translated list field not-any filter and int values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedInt: ['en' => 1, 'de' => 2]),
+ self::document(key: 'key2', translatedInt: ['en' => 2]),
+ self::document(key: 'key3', translatedInt: ['en' => null, 'de' => 2]),
+ self::document(key: 'key4', translatedInt: ['de' => 2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedInt', value: [1, 2])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+
+ yield 'Test translated list field equals filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated list field equals-any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 3.3]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedFloat', value: [2.2, 3.3])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 3.3]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated list field not filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedFloat', value: 2.2)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ ])
+ ];
+ yield 'Test translated list field not-any filter and float values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedFloat: ['en' => 1.1, 'de' => 2.2]),
+ self::document(key: 'key2', translatedFloat: ['en' => 2.2]),
+ self::document(key: 'key3', translatedFloat: ['en' => null, 'de' => 2.2]),
+ self::document(key: 'key4', translatedFloat: ['de' => 2.2]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedFloat', value: [1.1, 2.2])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+
+ yield 'Test translated list field equals filter and bool values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Equals(field: 'translatedBool', value: false)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ])
+ ];
+ yield 'Test translated list field equals-any filter and bool values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => true]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Any(field: 'translatedBool', value: [false, true])
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => true]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ])
+ ];
+ yield 'Test translated list field not filter and bool values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Not(field: 'translatedBool', value: false)
+ ]
+ ),
+ 'expected' => new FilterResult([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ ])
+ ];
+ yield 'Test translated list field not-any filter and bool values' => [
+ 'input' => new Documents([
+ self::document(key: 'key1', translatedBool: ['en' => true, 'de' => false]),
+ self::document(key: 'key2', translatedBool: ['en' => false]),
+ self::document(key: 'key3', translatedBool: ['en' => null, 'de' => false]),
+ self::document(key: 'key4', translatedBool: ['de' => false]),
+ ]),
+ 'criteria' => new FilterCriteria(
+ filters: [
+ new Neither(field: 'translatedBool', value: [true, false])
+ ]
+ ),
+ 'expected' => new FilterResult([])
+ ];
+ }
+
+ private function getClient(): Client
+ {
+ if ($this->client === null) {
+ $this->client = new Client(
+ url: 'http://localhost:7700',
+ apiKey: 'UTbXxcv5T5Hq-nCYAjgPJ5lsBxf7PdhgiNexmoTByJk'
+ );
+ }
+
+ return $this->client;
+ }
+
+ public function getStorage(): FilterStorage
+ {
+ return new LiveMeilisearchStorage(
+ storage: new MeilisearchStorage(
+ client: $this->getClient(),
+ schema: $this->getSchema()
+ ),
+ client: $this->getClient(),
+ );
+ }
+
+ private function index(): Indexes
+ {
+ return $this->getClient()->index($this->getSchema()->source);
+ }
+
+ private function wait(): void
+ {
+ $tasks = new TasksQuery();
+ $tasks->setStatuses(['enqueued', 'processing']);
+
+ $tasks = $this->getClient()->getTasks($tasks);
+
+ $ids = array_map(fn($task) => $task['uid'], $tasks->getResults());
+
+ if (count($ids) === 0) {
+ return;
+ }
+
+ $this->getClient()->waitForTasks($ids);
+ }
+}