Skip to content

Commit 2be9ad2

Browse files
committed
Merge branch 'builder' into PHPLIB-1506
2 parents 24214b6 + 6bc447f commit 2be9ad2

File tree

919 files changed

+63861
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

919 files changed

+63861
-1
lines changed

.gitattributes

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ tests export-ignore
44
benchmark export-ignore
55
docs export-ignore
66
examples export-ignore
7+
generator export-ignore
78
mongo-orchestration export-ignore
89
stubs export-ignore
910
tools export-ignore
@@ -17,3 +18,9 @@ psalm-baseline.xml export-ignore
1718

1819
# Prevent generated build files from showing diffs in pull requests
1920
.evergreen/config/generated/** linguist-generated=true
21+
/src/Builder/Accumulator/*.php linguist-generated=true
22+
/src/Builder/Expression/*.php linguist-generated=true
23+
/src/Builder/Query/*.php linguist-generated=true
24+
/src/Builder/Projection/*.php linguist-generated=true
25+
/src/Builder/Stage/*.php linguist-generated=true
26+
/tests/Builder/*/Pipelines.php linguist-generated=true

generator/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Code Generator for MongoDB PHP Library
2+
3+
This subproject is used to generate the code that is committed to the repository.
4+
The `generator` directory is not included in `mongodb/builder` package and is not installed by Composer.
5+
6+
## Contributing
7+
8+
Updating the generated code can be done only by modifying the code generator, or its configuration.
9+
10+
To run the generator, you need to have PHP 8.1+ installed and Composer.
11+
12+
1. Move to the `generator` directory: `cd generator`
13+
1. Install dependencies: `composer install`
14+
1. Run the generator: `./generate`
15+
16+
## Configuration
17+
18+
The `generator/config/*.yaml` files contains the list of operators and stages that are supported by the library.
19+
20+
### Test pipelines
21+
22+
Each operator can contain a `tests` section with a list if pipelines. To represent specific BSON objects,
23+
it is necessary to use Yaml tags:
24+
25+
| BSON Type | Example |
26+
|-------------|--------------------------------------------------------|
27+
| Regex | `!bson_regex '^abc'` <br/> `!bson_regex ['^abc', 'i']` |
28+
| Int64 | `!bson_int64 '123456789'` |
29+
| Decimal128 | `!bson_decimal128 '0.9'` |
30+
| UTCDateTime | `!bson_utcdatetime 0` |
31+
| Binary | `!bson_binary 'IA=='` |
32+
33+
To add new test cases to operators, you can get inspiration from the official MongoDB documentation and use
34+
the `generator/js2yaml.html` web page to manually convert a pipeline array from JS to Yaml.

generator/composer.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "mongodb/code-generator",
3+
"type": "project",
4+
"repositories": [
5+
{
6+
"type": "path",
7+
"url": "../",
8+
"symlink": true
9+
}
10+
],
11+
"replace": {
12+
"symfony/polyfill-php80": "*",
13+
"symfony/polyfill-php81": "*"
14+
},
15+
"require": {
16+
"php": ">=8.1",
17+
"ext-mongodb": "^1.17.0",
18+
"mongodb/mongodb": "@dev",
19+
"nette/php-generator": "^4.1.5",
20+
"nikic/php-parser": "^5",
21+
"symfony/console": "^6.3|^7.0",
22+
"symfony/finder": "^6.3|^7.0",
23+
"symfony/yaml": "^6.3|^7.0"
24+
},
25+
"license": "Apache-2.0",
26+
"autoload": {
27+
"psr-4": {
28+
"MongoDB\\CodeGenerator\\": "src/"
29+
}
30+
},
31+
"config": {
32+
"sort-packages": true
33+
}
34+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# $schema: ../schema.json
2+
name: $accumulator
3+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/'
4+
type:
5+
- accumulator
6+
encode: object
7+
description: |
8+
Defines a custom accumulator function.
9+
New in MongoDB 4.4.
10+
arguments:
11+
-
12+
name: init
13+
type:
14+
- javascript
15+
description: |
16+
Function used to initialize the state. The init function receives its arguments from the initArgs array expression. You can specify the function definition as either BSON type Code or String.
17+
-
18+
name: initArgs
19+
type:
20+
- resolvesToArray
21+
optional: true
22+
description: |
23+
Arguments passed to the init function.
24+
-
25+
name: accumulate
26+
type:
27+
- javascript
28+
description: |
29+
Function used to accumulate documents. The accumulate function receives its arguments from the current state and accumulateArgs array expression. The result of the accumulate function becomes the new state. You can specify the function definition as either BSON type Code or String.
30+
-
31+
name: accumulateArgs
32+
type:
33+
- resolvesToArray
34+
description: |
35+
Arguments passed to the accumulate function. You can use accumulateArgs to specify what field value(s) to pass to the accumulate function.
36+
-
37+
name: merge
38+
type:
39+
- javascript
40+
description: |
41+
Function used to merge two internal states. merge must be either a String or Code BSON type. merge returns the combined result of the two merged states. For information on when the merge function is called, see Merge Two States with $merge.
42+
-
43+
name: finalize
44+
type:
45+
- javascript
46+
optional: true
47+
description: |
48+
Function used to update the result of the accumulation.
49+
-
50+
name: lang
51+
type:
52+
- string
53+
description: |
54+
The language used in the $accumulator code.
55+
56+
tests:
57+
-
58+
name: 'Use $accumulator to Implement the $avg Operator'
59+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/#use--accumulator-to-implement-the--avg-operator'
60+
pipeline:
61+
-
62+
$group:
63+
_id: '$author'
64+
avgCopies:
65+
$accumulator:
66+
init:
67+
$code: |-
68+
function() {
69+
return { count: 0, sum: 0 }
70+
}
71+
accumulate:
72+
$code: |-
73+
function(state, numCopies) {
74+
return { count: state.count + 1, sum: state.sum + numCopies }
75+
}
76+
accumulateArgs: [ "$copies" ],
77+
merge:
78+
$code: |-
79+
function(state1, state2) {
80+
return {
81+
count: state1.count + state2.count,
82+
sum: state1.sum + state2.sum
83+
}
84+
}
85+
finalize:
86+
$code: |-
87+
function(state) {
88+
return (state.sum / state.count)
89+
}
90+
lang: 'js'
91+
92+
-
93+
name: 'Use initArgs to Vary the Initial State by Group'
94+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/#use-initargs-to-vary-the-initial-state-by-group'
95+
pipeline:
96+
-
97+
$group:
98+
_id:
99+
city: '$city'
100+
restaurants:
101+
$accumulator:
102+
init:
103+
$code: |-
104+
function(city, userProfileCity) {
105+
return { max: city === userProfileCity ? 3 : 1, restaurants: [] }
106+
}
107+
initArgs:
108+
- '$city'
109+
- 'Bettles'
110+
accumulate:
111+
$code: |-
112+
function(state, restaurantName) {
113+
if (state.restaurants.length < state.max) {
114+
state.restaurants.push(restaurantName);
115+
}
116+
return state;
117+
}
118+
accumulateArgs:
119+
- '$name'
120+
merge:
121+
$code: |-
122+
function(state1, state2) {
123+
return {
124+
max: state1.max,
125+
restaurants: state1.restaurants.concat(state2.restaurants).slice(0, state1.max)
126+
}
127+
}
128+
finalize:
129+
$code: |-
130+
function(state) {
131+
return state.restaurants
132+
}
133+
lang: 'js'
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# $schema: ../schema.json
2+
name: $addToSet
3+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/addToSet/'
4+
type:
5+
- accumulator
6+
- window
7+
encode: single
8+
description: |
9+
Returns an array of unique expression values for each group. Order of the array elements is undefined.
10+
Changed in MongoDB 5.0: Available in the $setWindowFields stage.
11+
arguments:
12+
-
13+
name: expression
14+
type:
15+
- expression
16+
17+
tests:
18+
-
19+
name: 'Use in $group Stage'
20+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/addToSet/#use-in--group-stage'
21+
pipeline:
22+
- $group:
23+
_id:
24+
day:
25+
$dayOfYear:
26+
date: '$date'
27+
year:
28+
$year:
29+
date: '$date'
30+
itemsSold:
31+
$addToSet: '$item'
32+
-
33+
name: 'Use in $setWindowFields Stage'
34+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/addToSet/#use-in--setwindowfields-stage'
35+
pipeline:
36+
-
37+
$setWindowFields:
38+
partitionBy: '$state'
39+
sortBy:
40+
orderDate: 1
41+
output:
42+
cakeTypesForState:
43+
$addToSet: '$type'
44+
window:
45+
documents:
46+
- 'unbounded'
47+
- 'current'

generator/config/accumulator/avg.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# $schema: ../schema.json
2+
name: $avg
3+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg/'
4+
type:
5+
- accumulator
6+
- window
7+
encode: single
8+
description: |
9+
Returns an average of numerical values. Ignores non-numeric values.
10+
Changed in MongoDB 5.0: Available in the $setWindowFields stage.
11+
arguments:
12+
-
13+
name: expression
14+
type:
15+
- resolvesToNumber
16+
tests:
17+
-
18+
name: 'Use in $group Stage'
19+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg/#use-in--group-stage'
20+
pipeline:
21+
- $group:
22+
_id: '$item'
23+
avgAmount:
24+
$avg:
25+
$multiply:
26+
- '$price'
27+
- '$quantity'
28+
avgQuantity:
29+
$avg: '$quantity'
30+
-
31+
name: 'Use in $setWindowFields Stage'
32+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg/#use-in--setwindowfields-stage'
33+
pipeline:
34+
-
35+
$setWindowFields:
36+
partitionBy: '$state'
37+
sortBy:
38+
orderDate: 1
39+
output:
40+
averageQuantityForState:
41+
$avg: '$quantity'
42+
window:
43+
documents:
44+
- 'unbounded'
45+
- 'current'
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# $schema: ../schema.json
2+
name: $bottom
3+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottom/'
4+
type:
5+
- accumulator
6+
- window
7+
encode: object
8+
description: |
9+
Returns the bottom element within a group according to the specified sort order.
10+
New in MongoDB 5.2: Available in the $group and $setWindowFields stages.
11+
arguments:
12+
-
13+
name: sortBy
14+
type:
15+
- object # SortSpec
16+
description: |
17+
Specifies the order of results, with syntax similar to $sort.
18+
-
19+
name: output
20+
type:
21+
- expression
22+
description: |
23+
Represents the output for each element in the group and can be any expression.
24+
tests:
25+
-
26+
name: 'Find the Bottom Score'
27+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottom/#find-the-bottom-score'
28+
pipeline:
29+
-
30+
$match:
31+
gameId: 'G1'
32+
-
33+
$group:
34+
_id: '$gameId'
35+
playerId:
36+
$bottom:
37+
output:
38+
- '$playerId'
39+
- '$score'
40+
sortBy:
41+
score: -1
42+
-
43+
name: 'Finding the Bottom Score Across Multiple Games'
44+
link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottom/#finding-the-bottom-score-across-multiple-games'
45+
pipeline:
46+
-
47+
$group:
48+
_id: '$gameId'
49+
playerId:
50+
$bottom:
51+
output:
52+
- '$playerId'
53+
- '$score'
54+
sortBy:
55+
score: -1

0 commit comments

Comments
 (0)