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{
@@ -304,7 +308,7 @@ public function filterDocs(
304308
305309 foreach ($ this ->inMemoryConnection ['documents ' ][$ collectionName ] as $ docId => $ doc ) {
306310 if ($ filter ->match ($ doc , (string )$ docId )) {
307- $ filteredDocs [$ docId ] = $ doc ;
311+ $ filteredDocs [$ docId ] = [ ' doc ' => $ doc, ' docId ' => $ docId ] ;
308312 }
309313 }
310314
@@ -320,7 +324,61 @@ public function filterDocs(
320324 $ filteredDocs = \array_slice ($ filteredDocs , 0 , $ limit );
321325 }
322326
323- return new \ArrayIterator ($ filteredDocs );
327+ $ docsMap = [];
328+
329+ foreach ($ filteredDocs as $ docAndId ) {
330+ $ docsMap [$ docAndId ['docId ' ]] = $ docAndId ['doc ' ];
331+ }
332+
333+ return new \ArrayIterator ($ docsMap );
334+ }
335+
336+ /**
337+ * @param string $collectionName
338+ * @param PartialSelect $partialSelect
339+ * @param Filter $filter
340+ * @param int|null $skip
341+ * @param int|null $limit
342+ * @param OrderBy|null $orderBy
343+ * @return \Traversable list of docs
344+ */
345+ public function filterPartialDocs (
346+ string $ collectionName ,
347+ PartialSelect $ partialSelect ,
348+ Filter $ filter ,
349+ int $ skip = null ,
350+ int $ limit = null ,
351+ OrderBy $ orderBy = null ): \Traversable
352+ {
353+ $ this ->assertHasCollection ($ collectionName );
354+
355+ $ filteredDocs = [];
356+
357+ foreach ($ this ->inMemoryConnection ['documents ' ][$ collectionName ] as $ docId => $ doc ) {
358+ if ($ filter ->match ($ doc , (string )$ docId )) {
359+ $ filteredDocs [$ docId ] = ['doc ' => $ doc , 'docId ' => $ docId ];
360+ }
361+ }
362+
363+ $ filteredDocs = \array_values ($ filteredDocs );
364+
365+ if ($ orderBy !== null ) {
366+ $ this ->sort ($ filteredDocs , $ orderBy );
367+ }
368+
369+ if ($ skip !== null ) {
370+ $ filteredDocs = \array_slice ($ filteredDocs , $ skip , $ limit );
371+ } elseif ($ limit !== null ) {
372+ $ filteredDocs = \array_slice ($ filteredDocs , 0 , $ limit );
373+ }
374+
375+ $ docsMap = [];
376+
377+ foreach ($ filteredDocs as $ docAndId ) {
378+ $ docsMap [$ docAndId ['docId ' ]] = $ this ->transformToPartialDoc ($ docAndId ['doc ' ], $ partialSelect );
379+ }
380+
381+ return new \ArrayIterator ($ docsMap );
324382 }
325383
326384 /**
@@ -344,6 +402,23 @@ public function filterDocIds(
344402 return $ docIds ;
345403 }
346404
405+ /**
406+ * @inheritDoc
407+ */
408+ public function countDocs (string $ collectionName , Filter $ filter ) : int
409+ {
410+ $ this ->assertHasCollection ($ collectionName );
411+
412+ $ counter = 0 ;
413+ foreach ($ this ->inMemoryConnection ['documents ' ][$ collectionName ] as $ docId => $ doc ) {
414+ if ($ filter ->match ($ doc , $ docId )) {
415+ $ counter ++;
416+ }
417+ }
418+
419+ return $ counter ;
420+ }
421+
347422 private function hasDoc (string $ collectionName , string $ docId ): bool
348423 {
349424 if (! $ this ->hasCollection ($ collectionName )) {
@@ -489,12 +564,12 @@ private function sort(&$docs, OrderBy $orderBy)
489564 if ($ orderBy instanceof Asc || $ orderBy instanceof Desc) {
490565 $ field = $ orderBy ->prop ();
491566
492- return (new ArrayReader ($ doc ))->mixedValue ($ field );
567+ return (new ArrayReader ($ doc[ ' doc ' ] ))->mixedValue ($ field );
493568 }
494569
495570 throw new \RuntimeException (\sprintf (
496571 'Unable to get field from doc: %s. Given OrderBy is neither an instance of %s nor %s ' ,
497- \json_encode ($ doc ),
572+ \json_encode ($ doc[ ' doc ' ] ),
498573 Asc::class,
499574 Desc::class
500575 ));
@@ -573,20 +648,43 @@ private function isSequentialArray(array $array): bool
573648 return \array_keys ($ array ) === \range (0 , \count ($ array ) - 1 );
574649 }
575650
576- /**
577- * @inheritDoc
578- */
579- public function countDocs (string $ collectionName , Filter $ filter ) : int
651+ private function transformToPartialDoc (array $ doc , PartialSelect $ partialSelect ): array
580652 {
581- $ this ->assertHasCollection ($ collectionName );
653+ $ partialDoc = [];
654+ $ reader = new ArrayReader ($ doc );
582655
583- $ counter = 0 ;
584- foreach ($ this ->inMemoryConnection ['documents ' ][$ collectionName ] as $ docId => $ doc ) {
585- if ($ filter ->match ($ doc , $ docId )) {
586- $ counter ++;
656+ foreach ($ partialSelect ->fieldAliasMap () as ['field ' => $ field , 'alias ' => $ alias ]) {
657+ $ value = $ reader ->mixedValue ($ field );
658+
659+ if ($ alias === PartialSelect::MERGE_ALIAS ) {
660+ if (null === $ value ) {
661+ continue ;
662+ }
663+
664+ if (!is_array ($ value )) {
665+ throw new RuntimeException ('Merge not possible. $merge alias was specified for field: ' . $ field . ' but field value is not an array: ' . json_encode ($ value ));
666+ }
667+
668+ foreach ($ value as $ k => $ v ) {
669+ $ partialDoc [$ k ] = $ v ;
670+ }
671+
672+ continue ;
587673 }
674+
675+ $ keys = explode ('. ' , $ alias );
676+
677+ $ ref = &$ partialDoc ;
678+ foreach ($ keys as $ i => $ key ) {
679+ if (!array_key_exists ($ key , $ ref )) {
680+ $ ref [$ key ] = [];
681+ }
682+ $ ref = &$ ref [$ key ];
683+ }
684+ $ ref = $ value ;
685+ unset($ ref );
588686 }
589687
590- return $ counter ;
688+ return $ partialDoc ;
591689 }
592690}
0 commit comments