Skip to content
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

Can't add a filter on a text search #2733

Open
fullbl opened this issue Feb 21, 2025 · 2 comments
Open

Can't add a filter on a text search #2733

fullbl opened this issue Feb 21, 2025 · 2 comments

Comments

@fullbl
Copy link

fullbl commented Feb 21, 2025

Bug Report

Q A
BC Break yes
Version 5.0.1

Summary

When adding a filter, it goes always in first stage. If the query already have a match two stages will be created, making mongodb throw an exception.
Documentation states that $match stage that includes a $text must be the first stage in the pipeline.

Current behavior

The stage that comes from filters will always be the first in pipeline.

How to reproduce

  1. create a filter
final class ExcludeSoftDeletedFilter extends BsonFilter
{
    public function addFilterCriteria(ClassMetadata $targetDocument): array
    {
        return [
            'deletedAt' => null,
        ];
    }
}
  1. run a query with texts:
$this->createAggregationBuilder()
            ->match()
            ->field('field')
            ->text('value')
An exception occured, transforming to an Error resource. {"exception":"[object] (MongoDB\\Driver\\Exception\\CommandException(code: 17313): $match with $text is only allowed as the first pipeline stage at /var/www/html/vendor/mongodb/mongodb/src/Operation/Aggregate.php:383

Expected behavior

In my opinion, the CriteriaMerger should be used when merging the attributes, or there should be a "reorder" before submitting the query, so the text stage should go first

@GromNaN
Copy link
Member

GromNaN commented Feb 21, 2025

It seems that we need to apply the same kind of logic that we already have with $geoNear:

* 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
* containing the required query.

@fullbl
Copy link
Author

fullbl commented Feb 21, 2025

Something like this would work, don't know if it's optimal (I'm pretty new to mongodb):

$matchExpression = $this->applyFilters([]);
        if ($matchExpression !== []) {
            if ($this->getStage(0) instanceof Stage\MatchStage) {
                $merger = new CriteriaMerger;
                $pipeline[0]['$match'] = $merger->merge($pipeline[0]['$match'], $matchExpression);

                return $pipeline;
            }
            array_unshift($pipeline, ['$match' => $matchExpression]);
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants