-
-
Notifications
You must be signed in to change notification settings - Fork 515
Add support for using $text operator in a aggregation with a filter
#2739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| use GeoJson\Geometry\Point; | ||
| use MongoDB\Collection; | ||
| use OutOfRangeException; | ||
| use stdClass; | ||
| use TypeError; | ||
|
|
||
| use function array_map; | ||
|
|
@@ -264,6 +265,11 @@ public function getAggregation(array $options = []): IterableResult | |
| * @param bool $applyFilters Whether to apply filters on the aggregation | ||
| * pipeline stage | ||
| * | ||
| * For pipelines where the first stage is a $match stage, it will merge | ||
| * the document filters with the existing stage in a logical $and. This is | ||
| * required as $text operator can be used anywhere in the first $match stage | ||
| * or in the document filters. | ||
| * | ||
| * For pipelines where the first stage is a $geoNear stage, it will apply | ||
| * the document filters and discriminator queries to the query portion of | ||
| * the geoNear operation. For all other pipelines, it prepends a $match stage | ||
|
|
@@ -306,14 +312,20 @@ public function getPipeline(/* bool $applyFilters = true */): array | |
| return $pipeline; | ||
| } | ||
|
|
||
| if ($this->getStage(0) instanceof Stage\GeoNear) { | ||
| if (isset($pipeline[0]['$geoNear'])) { | ||
| $pipeline[0]['$geoNear']['query'] = $this->applyFilters($pipeline[0]['$geoNear']['query']); | ||
|
|
||
| return $pipeline; | ||
| } | ||
|
|
||
| if (isset($pipeline[0]['$match'])) { | ||
| $pipeline[0]['$match'] = $this->applyFilters($pipeline[0]['$match']); | ||
|
|
||
| return $pipeline; | ||
| } | ||
|
|
||
| $matchExpression = $this->applyFilters([]); | ||
| if ($matchExpression !== []) { | ||
| if ((array) $matchExpression !== []) { | ||
GromNaN marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| array_unshift($pipeline, ['$match' => $matchExpression]); | ||
| } | ||
|
|
||
|
|
@@ -696,18 +708,22 @@ public function addStage(Stage $stage): Stage | |
| /** | ||
| * Applies filters and discriminator queries to the pipeline | ||
| * | ||
| * @param array<string, mixed> $query | ||
| * @param array<string, mixed>|stdClass $query | ||
| * | ||
| * @return array<string, mixed> | ||
| * @return array<string, mixed>|stdClass | ||
| */ | ||
| private function applyFilters(array $query): array | ||
| private function applyFilters(array|stdClass $query): array|stdClass | ||
| { | ||
| if (! is_array($query)) { | ||
| $query = (array) $query; | ||
| } | ||
|
|
||
| $documentPersister = $this->getDocumentPersister(); | ||
|
|
||
| $query = $documentPersister->addDiscriminatorToPreparedQuery($query); | ||
| $query = $documentPersister->addFilterToPreparedQuery($query); | ||
|
|
||
| return $query; | ||
| return $query === [] ? (object) $query : $query; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to juggle between |
||
| } | ||
|
|
||
| private function getDocumentPersister(): DocumentPersister | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -368,6 +368,36 @@ public function testBuilderAppliesFilterAndDiscriminatorWithMatchStage(): void | |
| self::assertEquals($expectedPipeline, $builder->getPipeline()); | ||
| } | ||
|
|
||
| public function testBuilderMergeFilterAndDiscriminatorWithMatchStage(): void | ||
| { | ||
| $this->dm->getFilterCollection()->enable('testFilter'); | ||
| $filter = $this->dm->getFilterCollection()->getFilter('testFilter'); | ||
| $filter->setParameter('class', GuestServer::class); | ||
| $filter->setParameter('field', 'filtered'); | ||
| $filter->setParameter('value', true); | ||
|
|
||
| $builder = $this->dm->createAggregationBuilder(GuestServer::class); | ||
| $builder | ||
| ->match() | ||
| ->text('Paul'); | ||
|
|
||
| $expectedPipeline = [ | ||
| [ | ||
| '$match' => [ | ||
| '$and' => [ | ||
| [ | ||
| 'stype' => 'server_guest', | ||
| '$text' => ['$search' => 'Paul'], | ||
| ], | ||
| ['filtered' => true], | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The query here seems odd, but I understand that's because |
||
| ], | ||
| ], | ||
| ], | ||
| ]; | ||
|
|
||
| self::assertEquals($expectedPipeline, $builder->getPipeline()); | ||
| } | ||
|
|
||
| public function testBuilderAppliesFilterAndDiscriminatorWithGeoNearStage(): void | ||
| { | ||
| $this->dm->getFilterCollection()->enable('testFilter'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,7 +72,7 @@ public function testLimitDoesNotCreateExtraStage(): void | |
| ->geoNear(0, 0) | ||
| ->limit(1); | ||
|
|
||
| $stage = ['near' => [0, 0], 'spherical' => false, 'distanceField' => null, 'query' => [], 'num' => 1]; | ||
| self::assertSame([['$geoNear' => $stage]], $builder->getPipeline()); | ||
| $stage = ['near' => [0, 0], 'spherical' => false, 'distanceField' => null, 'query' => (object) [], 'num' => 1]; | ||
| self::assertEquals([['$geoNear' => $stage]], $builder->getPipeline()); | ||
|
Comment on lines
+75
to
+76
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was an error:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this suggest that the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explicitly fixed in #2743. |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more efficient and more resilient if we introduce changes on the
$pipelinearray like #2740.