Skip to content

Commit dbb22d3

Browse files
author
codeliner
committed
Add method to filter partial documents
Also make sure that filterDocs and filterPartialDocs return a \Traversable that provides docId as key.
1 parent f5d9caa commit dbb22d3

File tree

5 files changed

+480
-22
lines changed

5 files changed

+480
-22
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea
22
composer.lock
3-
vendor
3+
vendor
4+
.php_cs.cache

src/DocumentStore.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ public function deleteMany(string $collectionName, Filter $filter): void;
127127
public function getDoc(string $collectionName, string $docId): ?array;
128128

129129
/**
130+
* @deprecated use findDocs instead
131+
*
130132
* @param string $collectionName
131133
* @param Filter $filter
132134
* @param int|null $skip
@@ -137,6 +139,29 @@ public function getDoc(string $collectionName, string $docId): ?array;
137139
*/
138140
public function filterDocs(string $collectionName, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;
139141

142+
/**
143+
* @param string $collectionName
144+
* @param Filter $filter
145+
* @param int|null $skip
146+
* @param int|null $limit
147+
* @param OrderBy|null $orderBy
148+
* @return \Traversable list of docs with key being the docId and value being the stored doc
149+
* @throws UnknownCollection
150+
*/
151+
public function findDocs(string $collectionName, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;
152+
153+
/**
154+
* @param string $collectionName
155+
* @param PartialSelect $partialSelect
156+
* @param Filter $filter
157+
* @param int|null $skip
158+
* @param int|null $limit
159+
* @param OrderBy|null $orderBy
160+
* @return \Traversable list of docs with key being the docId and value being the stored doc
161+
* @throws UnknownCollection
162+
*/
163+
public function findPartialDocs(string $collectionName, PartialSelect $partialSelect, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;
164+
140165
/**
141166
* @param string $collectionName
142167
* @param Filter $filter

src/InMemoryDocumentStore.php

Lines changed: 144 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515
use EventEngine\DocumentStore\Exception\RuntimeException;
1616
use EventEngine\DocumentStore\Exception\UnknownCollection;
1717
use EventEngine\DocumentStore\Filter\AndFilter;
18-
use EventEngine\DocumentStore\Filter\AnyFilter;
1918
use EventEngine\DocumentStore\Filter\EqFilter;
2019
use EventEngine\DocumentStore\Filter\Filter;
2120
use EventEngine\DocumentStore\OrderBy\AndOrder;
2221
use EventEngine\DocumentStore\OrderBy\Asc;
2322
use EventEngine\DocumentStore\OrderBy\Desc;
2423
use EventEngine\DocumentStore\OrderBy\OrderBy;
2524
use EventEngine\Persistence\InMemoryConnection;
25+
use function array_key_exists;
26+
use function count;
27+
use function explode;
28+
use function is_array;
29+
use function json_encode;
2630

2731
final class InMemoryDocumentStore implements DocumentStore
2832
{
@@ -283,16 +287,94 @@ public function getDoc(string $collectionName, string $docId): ?array
283287
return $this->inMemoryConnection['documents'][$collectionName][$docId] ?? null;
284288
}
285289

290+
/**
291+
* @inheritDoc
292+
*/
293+
public function filterDocs(
294+
string $collectionName,
295+
Filter $filter,
296+
int $skip = null,
297+
int $limit = null,
298+
OrderBy $orderBy = null): \Traversable
299+
{
300+
$this->assertHasCollection($collectionName);
301+
302+
$filteredDocs = [];
303+
304+
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
305+
if ($filter->match($doc, (string)$docId)) {
306+
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
307+
}
308+
}
309+
310+
$filteredDocs = \array_values($filteredDocs);
311+
312+
if ($orderBy !== null) {
313+
$this->sort($filteredDocs, $orderBy);
314+
}
315+
316+
if ($skip !== null) {
317+
$filteredDocs = \array_slice($filteredDocs, $skip, $limit);
318+
} elseif ($limit !== null) {
319+
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
320+
}
321+
322+
return new \ArrayIterator($filteredDocs);
323+
}
324+
325+
/**
326+
* @inheritDoc
327+
*/
328+
public function findDocs(
329+
string $collectionName,
330+
Filter $filter,
331+
int $skip = null,
332+
int $limit = null,
333+
OrderBy $orderBy = null): \Traversable
334+
{
335+
$this->assertHasCollection($collectionName);
336+
337+
$filteredDocs = [];
338+
339+
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
340+
if ($filter->match($doc, (string)$docId)) {
341+
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
342+
}
343+
}
344+
345+
$filteredDocs = \array_values($filteredDocs);
346+
347+
if ($orderBy !== null) {
348+
$this->sort($filteredDocs, $orderBy);
349+
}
350+
351+
if ($skip !== null) {
352+
$filteredDocs = \array_slice($filteredDocs, $skip, $limit);
353+
} elseif ($limit !== null) {
354+
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
355+
}
356+
357+
$docsMap = [];
358+
359+
foreach ($filteredDocs as $docAndId) {
360+
$docsMap[$docAndId['docId']] = $docAndId['doc'];
361+
}
362+
363+
return new \ArrayIterator($docsMap);
364+
}
365+
286366
/**
287367
* @param string $collectionName
368+
* @param PartialSelect $partialSelect
288369
* @param Filter $filter
289370
* @param int|null $skip
290371
* @param int|null $limit
291372
* @param OrderBy|null $orderBy
292373
* @return \Traversable list of docs
293374
*/
294-
public function filterDocs(
375+
public function findPartialDocs(
295376
string $collectionName,
377+
PartialSelect $partialSelect,
296378
Filter $filter,
297379
int $skip = null,
298380
int $limit = null,
@@ -304,7 +386,7 @@ public function filterDocs(
304386

305387
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
306388
if ($filter->match($doc, (string)$docId)) {
307-
$filteredDocs[$docId] = $doc;
389+
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
308390
}
309391
}
310392

@@ -320,7 +402,13 @@ public function filterDocs(
320402
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
321403
}
322404

323-
return new \ArrayIterator($filteredDocs);
405+
$docsMap = [];
406+
407+
foreach ($filteredDocs as $docAndId) {
408+
$docsMap[$docAndId['docId']] = $this->transformToPartialDoc($docAndId['doc'], $partialSelect);
409+
}
410+
411+
return new \ArrayIterator($docsMap);
324412
}
325413

326414
/**
@@ -344,6 +432,23 @@ public function filterDocIds(
344432
return $docIds;
345433
}
346434

435+
/**
436+
* @inheritDoc
437+
*/
438+
public function countDocs(string $collectionName, Filter $filter) : int
439+
{
440+
$this->assertHasCollection($collectionName);
441+
442+
$counter = 0;
443+
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
444+
if ($filter->match($doc, $docId)) {
445+
$counter++;
446+
}
447+
}
448+
449+
return $counter;
450+
}
451+
347452
private function hasDoc(string $collectionName, string $docId): bool
348453
{
349454
if (! $this->hasCollection($collectionName)) {
@@ -489,12 +594,12 @@ private function sort(&$docs, OrderBy $orderBy)
489594
if ($orderBy instanceof Asc || $orderBy instanceof Desc) {
490595
$field = $orderBy->prop();
491596

492-
return (new ArrayReader($doc))->mixedValue($field);
597+
return (new ArrayReader($doc['doc']))->mixedValue($field);
493598
}
494599

495600
throw new \RuntimeException(\sprintf(
496601
'Unable to get field from doc: %s. Given OrderBy is neither an instance of %s nor %s',
497-
\json_encode($doc),
602+
\json_encode($doc['doc']),
498603
Asc::class,
499604
Desc::class
500605
));
@@ -573,20 +678,43 @@ private function isSequentialArray(array $array): bool
573678
return \array_keys($array) === \range(0, \count($array) - 1);
574679
}
575680

576-
/**
577-
* @inheritDoc
578-
*/
579-
public function countDocs(string $collectionName, Filter $filter) : int
681+
private function transformToPartialDoc(array $doc, PartialSelect $partialSelect): array
580682
{
581-
$this->assertHasCollection($collectionName);
683+
$partialDoc = [];
684+
$reader = new ArrayReader($doc);
582685

583-
$counter = 0;
584-
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
585-
if ($filter->match($doc, $docId)) {
586-
$counter++;
686+
foreach ($partialSelect->fieldAliasMap() as ['field' => $field, 'alias' => $alias]) {
687+
$value = $reader->mixedValue($field);
688+
689+
if($alias === PartialSelect::MERGE_ALIAS) {
690+
if(null === $value) {
691+
continue;
692+
}
693+
694+
if(!is_array($value)) {
695+
throw new RuntimeException('Merge not possible. $merge alias was specified for field: ' . $field . ' but field value is not an array: ' . json_encode($value));
696+
}
697+
698+
foreach ($value as $k => $v) {
699+
$partialDoc[$k] = $v;
700+
}
701+
702+
continue;
587703
}
704+
705+
$keys = explode('.', $alias);
706+
707+
$ref = &$partialDoc;
708+
foreach ($keys as $i => $key) {
709+
if(!array_key_exists($key, $ref)) {
710+
$ref[$key] = [];
711+
}
712+
$ref = &$ref[$key];
713+
}
714+
$ref = $value;
715+
unset($ref);
588716
}
589717

590-
return $counter;
718+
return $partialDoc;
591719
}
592720
}

0 commit comments

Comments
 (0)