mirror of https://github.com/mongodb/mongo
SERVER-114748 Process dropping fields when materializing result in JOO (#45240)
GitOrigin-RevId: b34440744ed2700cce07aeebd13cc8fd810959f1
This commit is contained in:
parent
1f7f8f8c54
commit
861513e6ea
|
|
@ -1604,3 +1604,328 @@ rightEmbeddingField: "k.y.z"
|
|||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
## 6. Basic example with a $project excluding a field from the base collection
|
||||
### No join opt
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$project" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "9A2C9BDFA638F0C7F703251AC894A297CDDB8AF81B931E490B488BCF87386796",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"asField" : "y",
|
||||
"foreignCollection" : "test.basic_joins_md_foreign2",
|
||||
"foreignField" : "b",
|
||||
"inputStage" : {
|
||||
"asField" : "x",
|
||||
"foreignCollection" : "test.basic_joins_md_foreign1",
|
||||
"foreignField" : "a",
|
||||
"inputStage" : {
|
||||
"inputStage" : {
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
"stage" : "PROJECTION_SIMPLE",
|
||||
"transformBy" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
"localField" : "a",
|
||||
"scanDirection" : "forward",
|
||||
"stage" : "EQ_LOOKUP_UNWIND",
|
||||
"strategy" : "HashJoin"
|
||||
},
|
||||
"localField" : "b",
|
||||
"planNodeId" : 4,
|
||||
"scanDirection" : "forward",
|
||||
"stage" : "EQ_LOOKUP_UNWIND",
|
||||
"strategy" : "HashJoin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### With bottom-up plan enumeration (left-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (right-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| HASH_JOIN_EMBEDDING [a = a]
|
||||
| leftEmbeddingField: "none"
|
||||
| rightEmbeddingField: "x"
|
||||
| | |
|
||||
| | COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| | direction: "forward"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (zig-zag)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With fixed order, index join
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration and indexes
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign2]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign2]
|
||||
| keyPattern: { "b" : 1 }
|
||||
| indexName: "b_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3233,3 +3233,335 @@ rightEmbeddingField: "k.y.z"
|
|||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
## 10. Basic example with a $project excluding a field from the base collection
|
||||
### No join opt
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$project" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: classic
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "9A2C9BDFA638F0C7F703251AC894A297CDDB8AF81B931E490B488BCF87386796",
|
||||
"stages" : [
|
||||
{
|
||||
"$cursor" : {
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStage" : {
|
||||
"direction" : "forward",
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
"isCached" : false,
|
||||
"stage" : "PROJECTION_SIMPLE",
|
||||
"transformBy" : {
|
||||
"_id" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"as" : "x",
|
||||
"foreignField" : "a",
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"localField" : "a",
|
||||
"unwinding" : {
|
||||
"preserveNullAndEmptyArrays" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"as" : "y",
|
||||
"foreignField" : "b",
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"localField" : "b",
|
||||
"unwinding" : {
|
||||
"preserveNullAndEmptyArrays" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### With bottom-up plan enumeration (left-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (right-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| HASH_JOIN_EMBEDDING [a = a]
|
||||
| leftEmbeddingField: "none"
|
||||
| rightEmbeddingField: "x"
|
||||
| | |
|
||||
| | COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| | direction: "forward"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (zig-zag)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With fixed order, index join
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration and indexes
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign2]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign2]
|
||||
| keyPattern: { "b" : 1 }
|
||||
| indexName: "b_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3193,3 +3193,328 @@ rightEmbeddingField: "k.y.z"
|
|||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
## 10. Basic example with a $project excluding a field from the base collection
|
||||
### No join opt
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$project" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "9A2C9BDFA638F0C7F703251AC894A297CDDB8AF81B931E490B488BCF87386796",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"asField" : "y",
|
||||
"foreignCollection" : "test.basic_joins_md_foreign2",
|
||||
"foreignField" : "b",
|
||||
"inputStage" : {
|
||||
"asField" : "x",
|
||||
"foreignCollection" : "test.basic_joins_md_foreign1",
|
||||
"foreignField" : "a",
|
||||
"inputStage" : {
|
||||
"inputStage" : {
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
"stage" : "PROJECTION_SIMPLE",
|
||||
"transformBy" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
"localField" : "a",
|
||||
"scanDirection" : "forward",
|
||||
"stage" : "EQ_LOOKUP_UNWIND",
|
||||
"strategy" : "HashJoin"
|
||||
},
|
||||
"localField" : "b",
|
||||
"planNodeId" : 4,
|
||||
"scanDirection" : "forward",
|
||||
"stage" : "EQ_LOOKUP_UNWIND",
|
||||
"strategy" : "HashJoin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### With bottom-up plan enumeration (left-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (right-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| HASH_JOIN_EMBEDDING [a = a]
|
||||
| leftEmbeddingField: "none"
|
||||
| rightEmbeddingField: "x"
|
||||
| | |
|
||||
| | COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| | direction: "forward"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (zig-zag)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With fixed order, index join
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration and indexes
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign2]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign2]
|
||||
| keyPattern: { "b" : 1 }
|
||||
| indexName: "b_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3233,3 +3233,335 @@ rightEmbeddingField: "k.y.z"
|
|||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
## 10. Basic example with a $project excluding a field from the base collection
|
||||
### No join opt
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$project" : {
|
||||
"_id" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: classic
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "9A2C9BDFA638F0C7F703251AC894A297CDDB8AF81B931E490B488BCF87386796",
|
||||
"stages" : [
|
||||
{
|
||||
"$cursor" : {
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStage" : {
|
||||
"direction" : "forward",
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
"isCached" : false,
|
||||
"stage" : "PROJECTION_SIMPLE",
|
||||
"transformBy" : {
|
||||
"_id" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"as" : "x",
|
||||
"foreignField" : "a",
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"localField" : "a",
|
||||
"unwinding" : {
|
||||
"preserveNullAndEmptyArrays" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"as" : "y",
|
||||
"foreignField" : "b",
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"localField" : "b",
|
||||
"unwinding" : {
|
||||
"preserveNullAndEmptyArrays" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### With bottom-up plan enumeration (left-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (right-deep)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| HASH_JOIN_EMBEDDING [a = a]
|
||||
| leftEmbeddingField: "none"
|
||||
| rightEmbeddingField: "x"
|
||||
| | |
|
||||
| | COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| | direction: "forward"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration (zig-zag)
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 44, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign2]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "x"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign1]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, nested loop joins
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With random order, seed 45, hash join enabled
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
HASH_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md_foreign1]
|
||||
| direction: "forward"
|
||||
|
|
||||
HASH_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With fixed order, index join
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "y"
|
||||
rightEmbeddingField: "none"
|
||||
| |
|
||||
| PROJECTION_SIMPLE
|
||||
| transformBy: { "_id" : false }
|
||||
| |
|
||||
| COLLSCAN [test.basic_joins_md]
|
||||
| direction: "forward"
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md_foreign2]
|
||||
direction: "forward"
|
||||
```
|
||||
### With bottom-up plan enumeration and indexes
|
||||
usedJoinOptimization: true
|
||||
|
||||
```
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [b = b]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "y"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign2]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign2]
|
||||
| keyPattern: { "b" : 1 }
|
||||
| indexName: "b_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
INDEXED_NESTED_LOOP_JOIN_EMBEDDING [a = a]
|
||||
leftEmbeddingField: "none"
|
||||
rightEmbeddingField: "x"
|
||||
| |
|
||||
| FETCH [test.basic_joins_md_foreign1]
|
||||
|
|
||||
| |
|
||||
| INDEX_PROBE_NODE [test.basic_joins_md_foreign1]
|
||||
| keyPattern: { "a" : 1 }
|
||||
| indexName: "a_1"
|
||||
| isMultiKey: false
|
||||
| isUnique: false
|
||||
| isSparse: false
|
||||
| isPartial: false
|
||||
|
|
||||
PROJECTION_SIMPLE
|
||||
transformBy: { "_id" : false }
|
||||
|
|
||||
COLLSCAN [test.basic_joins_md]
|
||||
direction: "forward"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -315,3 +315,12 @@ runBasicJoinTest([
|
|||
{$lookup: {from: foreignColl2.getName(), as: "k.y.z", localField: "w.y.d", foreignField: "d"}},
|
||||
{$unwind: "$k.y.z"},
|
||||
]);
|
||||
|
||||
section("Basic example with a $project excluding a field from the base collection");
|
||||
runBasicJoinTest([
|
||||
{$project: {_id: false}},
|
||||
{$lookup: {from: foreignColl1.getName(), as: "x", localField: "a", foreignField: "a"}},
|
||||
{$unwind: "$x"},
|
||||
{$lookup: {from: foreignColl2.getName(), as: "y", localField: "b", foreignField: "b"}},
|
||||
{$unwind: "$y"},
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1655,8 +1655,11 @@ std::pair<SbStage, PlanStageSlots> generateJoinResult(const BinaryJoinEmbeddingN
|
|||
nodes.emplace_back(leftOutputs.get(SlotBasedStageBuilder::kResult));
|
||||
}
|
||||
for (const auto& field : fieldEffect.getFieldList()) {
|
||||
if ((!node->rightEmbeddingField || field != node->rightEmbeddingField->fullPath()) &&
|
||||
(!node->leftEmbeddingField || field != node->leftEmbeddingField->fullPath())) {
|
||||
if (!fieldEffect.isAllowedField(field)) {
|
||||
paths.emplace_back(field);
|
||||
nodes.emplace_back(ProjectNode::Drop{});
|
||||
} else if ((!node->rightEmbeddingField || field != node->rightEmbeddingField->fullPath()) &&
|
||||
(!node->leftEmbeddingField || field != node->leftEmbeddingField->fullPath())) {
|
||||
paths.emplace_back(field);
|
||||
// TODO: SERVER-113230 in case of conflict, we give priority to the left side. Depending
|
||||
// on the join graph, an embedding having the same name of a top-level field in the base
|
||||
|
|
|
|||
Loading…
Reference in New Issue