Specify Which Fields to Return
On this page
Overview
In this guide, you can learn how to control which fields appear in documents returned from read operations with the MongoDB Kotlin driver.
Many read requests require only a subset of fields in a document. For example, when logging a user in you may only need their username, and not all of their profile information. By default, queries in MongoDB return all fields in matching documents. You can use a projection to return only the data you need.
A projection is a document that instructs MongoDB which fields of a document to return. Use the Projections class to construct a projection document.
Behavior
Projections work in two ways:
Explicitly including fields. This has the side-effect of implicitly excluding all unspecified fields.
Implicitly excluding fields. This has the side-effect of implicitly including all unspecified fields.
These two methods of projection are mutually exclusive: if you explicitly include fields, you cannot explicitly exclude fields, and vice versa.
Important
The _id
field is not subject to these mechanics. You must
explicitly exclude the _id
field if you do not want it returned.
You can exclude the _id
field even if you have specified certain
fields to include.
Explanation
Consider the following collection containing documents that describe varieties of fruit:
{ "_id": 1, "name": "apples", "qty": 5, "rating": 3 }, { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 }, { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 }, { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
This data is modeled using the following Kotlin data class:
data class Fruit( val id: Int, val name: String, val qty: Int, val rating: Int )
In the following query, pass the projection to return the name
field of each document. The results are modeled using the FruitName
Kotlin data class:
data class FruitName( val id: Int? = null, val name: String ) // Return all documents with only the name field val filter = Filters.empty() val projection = Projections.fields( Projections.include(FruitName::name.name) ) val flowResults = collection.find<FruitName>(filter).projection(projection) flowResults.collect { println(it)}
FruitName(id=1, name=apples), FruitName(id=2, name=bananas), FruitName(id=3, name=oranges), FruitName(id=4, name=avocados)
The projection document specifies that the read operation result should
include the name
field of each returned document. As a result, this
projection implicitly excludes the qty
and rating
fields. Chaining
this projection to find()
with an empty query filter yields the
above results.
Despite the fact that this projection only explicitly included the
name
field, the query also returned the _id
field, represented by id
in the data class.
The _id
field is a special case: it is always included in every query
result unless explicitly excluded. That's because the _id
field is a
unique identifier for each document, a property that can be useful when
constructing queries.
The _id
is the only exception to the mutually exclusive include-exclude
behavior in projections: you can explicitly exclude the _id
field
even when explicitly including other fields if you do not want _id
to be present in returned documents.
data class FruitName( val id: Int? = null, val name: String ) // Return all documents with *only* the name field // excludes the id val filter = Filters.empty() val projection = Projections.fields( Projections.include(FruitName::name.name), Projections.excludeId() ) val flowResults = collection.find<FruitName>(filter).projection(projection) flowResults.collect { println(it)}
FruitName(name=apples), FruitName(name=bananas), FruitName(name=oranges), FruitName(name=avocados)
The projection document specifies that the read operation result should
include the name
field of each returned document, and specifies to
exclude the _id
field. As a result, this projection implicitly
excludes the qty
and rating
fields. Chaining this projection to
find()
with an empty query filter yields the above results.
You can also specify multiple fields to include in your projection.
Tip
The order in which you specify the fields in the projection does not alter the order in which they are returned.
This example that identifies two fields to include in the projection yields
the following results using the FruitRating
Kotlin data class:
data class FruitRating( val name: String, val rating: Int ) val filter = Filters.empty() val projection = Projections.fields( Projections.include(FruitRating::name.name, FruitRating::rating.name), Projections.excludeId() ) val flowResults = collection.find<FruitRating>(filter).projection(projection) flowResults.collect { println(it)}
FruitRating(name=apples, rating=3), FruitRating(name=bananas, rating=1), FruitRating(name=oranges, rating=2), FruitRating(name=avocados, rating=5)
For additional projection examples, see the MongoDB Manual page on Project Fields to Return from Query.