Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
composer.lock
vendor
vendor
.php_cs.cache
25 changes: 25 additions & 0 deletions src/DocumentStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public function deleteMany(string $collectionName, Filter $filter): void;
public function getDoc(string $collectionName, string $docId): ?array;

/**
* @deprecated use findDocs instead
*
* @param string $collectionName
* @param Filter $filter
* @param int|null $skip
Expand All @@ -137,6 +139,29 @@ public function getDoc(string $collectionName, string $docId): ?array;
*/
public function filterDocs(string $collectionName, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;

/**
* @param string $collectionName
* @param Filter $filter
* @param int|null $skip
* @param int|null $limit
* @param OrderBy|null $orderBy
* @return \Traversable list of docs with key being the docId and value being the stored doc
* @throws UnknownCollection
*/
public function findDocs(string $collectionName, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;

/**
* @param string $collectionName
* @param PartialSelect $partialSelect
* @param Filter $filter
* @param int|null $skip
* @param int|null $limit
* @param OrderBy|null $orderBy
* @return \Traversable list of docs with key being the docId and value being the stored doc
* @throws UnknownCollection
*/
public function findPartialDocs(string $collectionName, PartialSelect $partialSelect, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable;

/**
* @param string $collectionName
* @param Filter $filter
Expand Down
166 changes: 150 additions & 16 deletions src/InMemoryDocumentStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
use EventEngine\DocumentStore\Exception\RuntimeException;
use EventEngine\DocumentStore\Exception\UnknownCollection;
use EventEngine\DocumentStore\Filter\AndFilter;
use EventEngine\DocumentStore\Filter\AnyFilter;
use EventEngine\DocumentStore\Filter\EqFilter;
use EventEngine\DocumentStore\Filter\Filter;
use EventEngine\DocumentStore\OrderBy\AndOrder;
use EventEngine\DocumentStore\OrderBy\Asc;
use EventEngine\DocumentStore\OrderBy\Desc;
use EventEngine\DocumentStore\OrderBy\OrderBy;
use EventEngine\Persistence\InMemoryConnection;
use function array_key_exists;
use function count;
use function explode;
use function is_array;
use function json_encode;

final class InMemoryDocumentStore implements DocumentStore
{
Expand Down Expand Up @@ -283,16 +287,100 @@ public function getDoc(string $collectionName, string $docId): ?array
return $this->inMemoryConnection['documents'][$collectionName][$docId] ?? null;
}

/**
* @inheritDoc
*/
public function filterDocs(
string $collectionName,
Filter $filter,
int $skip = null,
int $limit = null,
OrderBy $orderBy = null): \Traversable
{
$this->assertHasCollection($collectionName);

$filteredDocs = [];

foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
if ($filter->match($doc, (string)$docId)) {
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
}
}

$filteredDocs = \array_values($filteredDocs);

if ($orderBy !== null) {
$this->sort($filteredDocs, $orderBy);
}

if ($skip !== null) {
$filteredDocs = \array_slice($filteredDocs, $skip, $limit);
} elseif ($limit !== null) {
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
}

$docsMap = [];

foreach ($filteredDocs as $docAndId) {
$docsMap[] = $docAndId['doc'];
}

return new \ArrayIterator($docsMap);
}

/**
* @inheritDoc
*/
public function findDocs(
string $collectionName,
Filter $filter,
int $skip = null,
int $limit = null,
OrderBy $orderBy = null): \Traversable
{
$this->assertHasCollection($collectionName);

$filteredDocs = [];

foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
if ($filter->match($doc, (string)$docId)) {
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
}
}

$filteredDocs = \array_values($filteredDocs);

if ($orderBy !== null) {
$this->sort($filteredDocs, $orderBy);
}

if ($skip !== null) {
$filteredDocs = \array_slice($filteredDocs, $skip, $limit);
} elseif ($limit !== null) {
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
}

$docsMap = [];

foreach ($filteredDocs as $docAndId) {
$docsMap[$docAndId['docId']] = $docAndId['doc'];
}

return new \ArrayIterator($docsMap);
}

/**
* @param string $collectionName
* @param PartialSelect $partialSelect
* @param Filter $filter
* @param int|null $skip
* @param int|null $limit
* @param OrderBy|null $orderBy
* @return \Traversable list of docs
*/
public function filterDocs(
public function findPartialDocs(
string $collectionName,
PartialSelect $partialSelect,
Filter $filter,
int $skip = null,
int $limit = null,
Expand All @@ -304,7 +392,7 @@ public function filterDocs(

foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
if ($filter->match($doc, (string)$docId)) {
$filteredDocs[$docId] = $doc;
$filteredDocs[$docId] = ['doc' => $doc, 'docId' => $docId];
}
}

Expand All @@ -320,7 +408,13 @@ public function filterDocs(
$filteredDocs = \array_slice($filteredDocs, 0, $limit);
}

return new \ArrayIterator($filteredDocs);
$docsMap = [];

foreach ($filteredDocs as $docAndId) {
$docsMap[$docAndId['docId']] = $this->transformToPartialDoc($docAndId['doc'], $partialSelect);
}

return new \ArrayIterator($docsMap);
}

/**
Expand All @@ -344,6 +438,23 @@ public function filterDocIds(
return $docIds;
}

/**
* @inheritDoc
*/
public function countDocs(string $collectionName, Filter $filter) : int
{
$this->assertHasCollection($collectionName);

$counter = 0;
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
if ($filter->match($doc, $docId)) {
$counter++;
}
}

return $counter;
}

private function hasDoc(string $collectionName, string $docId): bool
{
if (! $this->hasCollection($collectionName)) {
Expand Down Expand Up @@ -489,12 +600,12 @@ private function sort(&$docs, OrderBy $orderBy)
if ($orderBy instanceof Asc || $orderBy instanceof Desc) {
$field = $orderBy->prop();

return (new ArrayReader($doc))->mixedValue($field);
return (new ArrayReader($doc['doc']))->mixedValue($field);
}

throw new \RuntimeException(\sprintf(
'Unable to get field from doc: %s. Given OrderBy is neither an instance of %s nor %s',
\json_encode($doc),
\json_encode($doc['doc']),
Asc::class,
Desc::class
));
Expand Down Expand Up @@ -573,20 +684,43 @@ private function isSequentialArray(array $array): bool
return \array_keys($array) === \range(0, \count($array) - 1);
}

/**
* @inheritDoc
*/
public function countDocs(string $collectionName, Filter $filter) : int
private function transformToPartialDoc(array $doc, PartialSelect $partialSelect): array
{
$this->assertHasCollection($collectionName);
$partialDoc = [];
$reader = new ArrayReader($doc);

$counter = 0;
foreach ($this->inMemoryConnection['documents'][$collectionName] as $docId => $doc) {
if ($filter->match($doc, $docId)) {
$counter++;
foreach ($partialSelect->fieldAliasMap() as ['field' => $field, 'alias' => $alias]) {
$value = $reader->mixedValue($field);

if($alias === PartialSelect::MERGE_ALIAS) {
if(null === $value) {
continue;
}

if(!is_array($value)) {
throw new RuntimeException('Merge not possible. $merge alias was specified for field: ' . $field . ' but field value is not an array: ' . json_encode($value));
}

foreach ($value as $k => $v) {
$partialDoc[$k] = $v;
}

continue;
}

$keys = explode('.', $alias);

$ref = &$partialDoc;
foreach ($keys as $i => $key) {
if(!array_key_exists($key, $ref)) {
$ref[$key] = [];
}
$ref = &$ref[$key];
}
$ref = $value;
unset($ref);
}

return $counter;
return $partialDoc;
}
}
Loading