Rename a Field in the Query Results in MongoDB

Sometimes when you query a collection in MongoDB, you might not be happy with the field names. By default, the field names are simply a reflection of the field names in the actual documents.

Perhaps the field names are inconsistent, or there’s a typo. Whatever the reason, you can use the $project aggregation pipeline stage to rename a field in your query results.

In some ways, this is comparable to using an alias in SQL, as it doesn’t rename the underlying fields, it simply renames them in the query results.

Example

Suppose we return the contents of a collection like this:

db.employees.find()

Result:

{ "_id" : 2, "name" : "Sarah", "salary" : 128000 }
{ "_id" : 3, "name" : "Fritz", "salary" : 25000 }
{ "_id" : 4, "name" : "Chris", "salary" : 45000 }
{ "_id" : 5, "name" : "Beck", "salary" : 82000 }

Here, we use the find() method to return the contents of the collection.

In this case, the names of each field are returned in the results.

But what if we wanted the field names to be different? For example, what if we want to replace name with employee?

In that case we could use the aggregate() method to perform a query like this:

db.employees.aggregate([
  { "$project": { "employee": "$name", "salary": 1 }}
])

Result:

{ "_id" : 2, "salary" : 128000, "employee" : "Sarah" }
{ "_id" : 3, "salary" : 25000, "employee" : "Fritz" }
{ "_id" : 4, "salary" : 45000, "employee" : "Chris" }
{ "_id" : 5, "salary" : 82000, "employee" : "Beck" }

Note that MongoDB displays the fields in the order of insertion, which results in the salary field being presented before the employee field. If that’s unacceptable, we can always change the query to this:

db.employees.aggregate([
  { "$project": { "employee": "$name", "salary": "$salary" }}
])

Result:

{ "_id" : 2, "employee" : "Sarah", "salary" : 128000 }
{ "_id" : 3, "employee" : "Fritz", "salary" : 25000 }
{ "_id" : 4, "employee" : "Chris", "salary" : 45000 }
{ "_id" : 5, "employee" : "Beck", "salary" : 82000 }

Rename Fields in Embedded Documents

You can use the same method to rename fields in embedded documents. In this case, use dot-notation to refer to the field that you want to rename.

Suppose we run the following query against a pets collection:

db.pets.find().pretty()

Result:

{
	"_id" : 1,
	"name" : "Wag",
	"details" : {
		"type" : "Dog",
		"weight" : 20,
		"awards" : {
			"Florida Dog Awards" : "Top Dog",
			"New York Marathon" : "Fastest Dog",
			"Sumo 2020" : "Biggest Dog"
		}
	}
}
{
	"_id" : 2,
	"name" : "Fetch",
	"details" : {
		"born" : ISODate("2020-06-22T14:00:00Z"),
		"color" : "Black"
	}
}
{
	"_id" : 3,
	"name" : "Scratch",
	"details" : {
		"eats" : [
			"Mouse Porridge",
			"Bird Soup",
			"Caviar"
		],
		"type" : "Cat",
		"born" : ISODate("2020-12-19T14:00:00Z")
	}
}

We can rename fields on the embedded documents like this:

db.pets.aggregate([
  { "$project": 
    { 
      "_id": 0,
      "Pet": "$name",
      "Type": "$details.type",
      "Born": "$details.born"
    }
  }
])

Result:

{ "Pet" : "Wag", "Type" : "Dog" }
{ "Pet" : "Fetch", "Born" : ISODate("2020-06-22T14:00:00Z") }
{ "Pet" : "Scratch", "Type" : "Cat", "Born" : ISODate("2020-12-19T14:00:00Z") }

In this case I didn’t select all fields in the embedded documents, but you get the idea.

I also used "_id": 0 to omit the _id field.

Also note that if a document doesn’t actually have a field that’s specified in the $project stage, then it will simply be omitted in the resulting document. You can see this in the first document, which omits the Born field, and the second document, which omits the Type field.