Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-27115

Track fields renamed by $project in aggregation for index consideration

    Details

    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Steps To Reproduce:
      Hide

      > db.version()
      3.4.0-rc1
      > c.createIndex({x:1})
      {
      	"createdCollectionAutomatically" : false,
      	"numIndexesBefore" : 1,
      	"numIndexesAfter" : 2,
      	"ok" : 1
      }
      > c.explain().aggregate([{$project:{x_renamed:"$x"}},{$match:{"x_renamed" : 1}}])
      {
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					
      				},
      				"fields" : {
      					"x" : 1,
      					"_id" : 1
      				},
      				"queryPlanner" : {
      					"plannerVersion" : 1,
      					"namespace" : "test.col",
      					"indexFilterSet" : false,
      					"parsedQuery" : {
      						
      					},
      					"winningPlan" : {
      						"stage" : "COLLSCAN",
      						"direction" : "forward"
      					},
      					"rejectedPlans" : [ ]
      				}
      			}
      		},
      		{
      			"$project" : {
      				"_id" : true,
      				"x_renamed" : "$x"
      			}
      		},
      		{
      			"$match" : {
      				"x_renamed" : 1
      			}
      		}
      	],
      	"ok" : 1
      }
      >
      >//Compared to $matching on the original field name (after SERVER-19153)
      >
      > c.explain().aggregate([{$project:{x:1}},{$match:{"x" : 1}}])
      {
      	"stages" : [
      		{
      			"$cursor" : {
      				"query" : {
      					"x" : 1
      				},
      				"fields" : {
      					"x" : 1,
      					"_id" : 1
      				},
      				"queryPlanner" : {
      					"plannerVersion" : 1,
      					"namespace" : "test.col",
      					"indexFilterSet" : false,
      					"parsedQuery" : {
      						"x" : {
      							"$eq" : 1
      						}
      					},
      					"winningPlan" : {
      						"stage" : "FETCH",
      						"inputStage" : {
      							"stage" : "IXSCAN",
      							"keyPattern" : {
      								"x" : 1
      							},
      							"indexName" : "x_1",
      							"isMultiKey" : false,
      							"multiKeyPaths" : {
      								"x" : [ ]
      							},
      							"isUnique" : false,
      							"isSparse" : false,
      							"isPartial" : false,
      							"indexVersion" : 2,
      							"direction" : "forward",
      							"indexBounds" : {
      								"x" : [
      									"[1.0, 1.0]"
      								]
      							}
      						}
      					},
      					"rejectedPlans" : [ ]
      				}
      			}
      		},
      		{
      			"$project" : {
      				"_id" : true,
      				"x" : true
      			}
      		}
      	],
      	"ok" : 1
      }
      

      Show
      > db.version() 3.4.0-rc1 > c.createIndex({x:1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } > c.explain().aggregate([{$project:{x_renamed:"$x"}},{$match:{"x_renamed" : 1}}]) { "stages" : [ { "$cursor" : { "query" : { }, "fields" : { "x" : 1, "_id" : 1 }, "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.col", "indexFilterSet" : false, "parsedQuery" : { }, "winningPlan" : { "stage" : "COLLSCAN", "direction" : "forward" }, "rejectedPlans" : [ ] } } }, { "$project" : { "_id" : true, "x_renamed" : "$x" } }, { "$match" : { "x_renamed" : 1 } } ], "ok" : 1 } > >//Compared to $matching on the original field name (after SERVER-19153) > > c.explain().aggregate([{$project:{x:1}},{$match:{"x" : 1}}]) { "stages" : [ { "$cursor" : { "query" : { "x" : 1 }, "fields" : { "x" : 1, "_id" : 1 }, "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.col", "indexFilterSet" : false, "parsedQuery" : { "x" : { "$eq" : 1 } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "x" : 1 }, "indexName" : "x_1", "isMultiKey" : false, "multiKeyPaths" : { "x" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "x" : [ "[1.0, 1.0]" ] } } }, "rejectedPlans" : [ ] } } }, { "$project" : { "_id" : true, "x" : true } } ], "ok" : 1 }
    • Epic Link:
    • Sprint:
      Query 2017-03-27, Query 2017-04-17, Query 2017-05-08, Query 2017-05-29, Query 2017-06-19

      Description

      Simply renaming a field in a $project currently disqualifies it from index consideration. The database should track simple field name changes in order to preserve index options.

      This is particularly relevant since SERVER-19153 has been implemented and views are being introduced. In addition to BI use cases, consider that views would allow for more compact field names be stored in the collection and then expanded out via the view definition (eg: fn -> firstname).

      Implementation of this feature would allow for more flexibility in how logically equivalent aggregation pipelines are written while optimal performance is maintained.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                13 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: