Skip to content
This repository was archived by the owner on Feb 28, 2025. It is now read-only.

PHPLIB-1336 Add tests on Evaluation Query Operators #24

Merged
merged 1 commit into from
Jan 16, 2024
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
26 changes: 26 additions & 0 deletions generator/config/query/jsonSchema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,29 @@ arguments:
name: schema
type:
- object
tests:
-
name: 'Example'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/jsonSchema/#syntax'
pipeline:
-
$match:
$jsonSchema:
required:
- 'name'
- 'major'
- 'gpa'
- 'address'
properties:
name:
bsonType: 'string'
description: 'must be a string and is required'
address:
bsonType: 'object'
required:
- 'zipcode'
properties:
street:
bsonType: 'string'
zipcode:
bsonType: 'string'
29 changes: 27 additions & 2 deletions generator/config/query/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,33 @@ arguments:
-
name: divisor
type:
- int
- number
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspected there were a few more that I missed previously. Thanks for finding those 🎉

-
name: remainder
type:
- int
- number
tests:
-
name: 'Use $mod to Select Documents'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/mod/#use--mod-to-select-documents'
pipeline:
-
$match:
qty:
$mod: [4, 0]
-
name: 'Floating Point Arguments'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/mod/#floating-point-arguments'
pipeline:
-
$match:
qty:
$mod: [4.0, 0]
-
$match:
qty:
$mod: [4.5, 0]
-
$match:
qty:
$mod: [4.99, 0]
76 changes: 75 additions & 1 deletion generator/config/query/text.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: $text
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/'
type:
- query
encode: object
encode: dollar_object
description: |
Performs text search.
arguments:
Expand Down Expand Up @@ -36,3 +36,77 @@ arguments:
description: |
A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes. Defaults to false; i.e. the search defers to the diacritic insensitivity of the text index.
Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index.
tests:
-
name: 'Search for a Single Word'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#search-for-a-single-word'
pipeline:
-
$match:
$text:
$search: 'coffee'
-
name: 'Match Any of the Search Terms'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#search-for-a-single-word'
pipeline:
-
$match:
$text:
$search: 'bake coffee cake'
-
name: 'Search a Different Language'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#search-a-different-language'
pipeline:
-
$match:
$text:
$search: 'leche'
$language: 'es'
-
name: 'Case and Diacritic Insensitive Search'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#case-and-diacritic-insensitive-search'
pipeline:
-
$match:
$text:
$search: 'сы́рники CAFÉS'
-
name: 'Perform Case Sensitive Search'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#perform-case-sensitive-search'
pipeline:
-
$match:
$text:
$search: 'Coffee'
$caseSensitive: true
-
$match:
$text:
$search: '\"Café Con Leche\"'
$caseSensitive: true
-
name: 'Diacritic Sensitive Search'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#perform-case-sensitive-search'
pipeline:
-
$match:
$text:
$search: 'CAFÉ'
$diacriticSensitive: true
-
name: 'Text Search Score Examples'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/text/#perform-case-sensitive-search'
pipeline:
-
$match:
$text:
$search: 'CAFÉ'
$diacriticSensitive: true
score:
$meta: 'textScore'
-
$sort:
score:
$meta: 'textScore'
-
$limit: 5
18 changes: 18 additions & 0 deletions generator/config/query/where.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,21 @@ arguments:
name: function
type:
- javascript
tests:
-
name: 'Example'
link: 'https://www.mongodb.com/docs/manual/reference/operator/query/where/#example'
pipeline:
-
$match:
$where: 'function() { return hex_md5(this.name) == "9b53e667f30cd329dca1ec9e6a83e994" }'
-
$match:
$expr:
$function:
body: |-
function(name) {
return hex_md5(name) == "9b53e667f30cd329dca1ec9e6a83e994";
}
args: ['$name']
lang: 'js'
1 change: 1 addition & 0 deletions generator/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"enum": [
"array",
"object",
"dollar_object",
"single",
"group"
]
Expand Down
1 change: 1 addition & 0 deletions generator/src/Definition/OperatorDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function __construct(
'single' => Encode::Single,
'array' => Encode::Array,
'object' => Encode::Object,
'dollar_object' => Encode::DollarObject,
'group' => Encode::Group,
default => throw new UnexpectedValueException(sprintf('Unexpected "encode" value for operator "%s". Got "%s"', $name, $encode)),
};
Expand Down
18 changes: 18 additions & 0 deletions src/Builder/BuilderEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ public function encode($value): stdClass|array|string
case Encode::Object:
return $this->encodeAsObject($value);

case Encode::DollarObject:
return $this->encodeAsDollarObject($value);

case Encode::Group:
assert($value instanceof GroupStage);

Expand Down Expand Up @@ -170,6 +173,21 @@ private function encodeAsObject(OperatorInterface $value): stdClass
return $this->wrap($value, $result);
}

private function encodeAsDollarObject(OperatorInterface $value): stdClass
{
$result = new stdClass();
foreach (get_object_vars($value) as $key => $val) {
// Skip optional arguments. If they have a default value, it is resolved by the server.
if ($val === Optional::Undefined) {
continue;
}

$result->{'$' . $key} = $this->recursiveEncode($val);
}

return $this->wrap($value, $result);
}

/**
* Get the unique property of the operator as value
*/
Expand Down
9 changes: 6 additions & 3 deletions src/Builder/Query/FactoryTrait.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions src/Builder/Query/ModOperator.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Builder/Query/TextOperator.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Builder/Type/Encode.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ enum Encode
*/
case Object;

/**
* Parameters are encoded as an object with keys matching the parameter names prefixed with a dollar sign ($)
*/
case DollarObject;

/**
* Get the single parameter value
*/
Expand Down
45 changes: 45 additions & 0 deletions tests/Builder/Query/JsonSchemaOperatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace MongoDB\Tests\Builder\Query;

use MongoDB\Builder\Pipeline;
use MongoDB\Builder\Query;
use MongoDB\Builder\Stage;
use MongoDB\Tests\Builder\PipelineTestCase;

use function MongoDB\object;

/**
* Test $jsonSchema query
*/
class JsonSchemaOperatorTest extends PipelineTestCase
{
public function testExample(): void
{
$pipeline = new Pipeline(
Stage::match(
Query::jsonSchema(object(
required: ['name', 'major', 'gpa', 'address'],
properties: object(
name: object(
bsonType: 'string',
description: 'must be a string and is required',
),
address: object(
bsonType: 'object',
required: ['zipcode'],
properties: object(
zipcode: object(bsonType: 'string'),
street: object(bsonType: 'string'),
),
),
),
)),
),
);

$this->assertSamePipeline(Pipelines::JsonSchemaExample, $pipeline);
}
}
44 changes: 44 additions & 0 deletions tests/Builder/Query/ModOperatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace MongoDB\Tests\Builder\Query;

use MongoDB\Builder\Pipeline;
use MongoDB\Builder\Query;
use MongoDB\Builder\Stage;
use MongoDB\Tests\Builder\PipelineTestCase;

/**
* Test $mod query
*/
class ModOperatorTest extends PipelineTestCase
{
public function testFloatingPointArguments(): void
{
$pipeline = new Pipeline(
Stage::match(
qty: Query::mod(4.0, 0),
),
Stage::match(
qty: Query::mod(4.5, 0),
),
Stage::match(
qty: Query::mod(4.99, 0),
),
);

$this->assertSamePipeline(Pipelines::ModFloatingPointArguments, $pipeline);
}

public function testUseModToSelectDocuments(): void
{
$pipeline = new Pipeline(
Stage::match(
qty: Query::mod(4, 0),
),
);

$this->assertSamePipeline(Pipelines::ModUseModToSelectDocuments, $pipeline);
}
}
Loading