1515use EventEngine \DocumentStore \Exception \RuntimeException ;
1616use EventEngine \DocumentStore \Exception \UnknownCollection ;
1717use EventEngine \DocumentStore \Filter \AndFilter ;
18- use EventEngine \DocumentStore \Filter \AnyFilter ;
1918use EventEngine \DocumentStore \Filter \EqFilter ;
2019use EventEngine \DocumentStore \Filter \Filter ;
2120use EventEngine \DocumentStore \OrderBy \AndOrder ;
2221use EventEngine \DocumentStore \OrderBy \Asc ;
2322use EventEngine \DocumentStore \OrderBy \Desc ;
2423use EventEngine \DocumentStore \OrderBy \OrderBy ;
2524use 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
2731final 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