Overview
En esta guía, puede aprender a especificar proyecciones utilizando constructores en el controlador MongoDB Kotlin.
MongoDB admite la proyección de campos, especificando qué campos incluir y excluir al devolver resultados de una consulta. La proyección en MongoDB sigue algunas reglas básicas:
El
_idEl campo siempre se incluye a menos que se excluya explícitamenteAl especificar un campo para su inclusión se excluyen implícitamente todos los demás campos excepto el
_idcampoAl especificar un campo para exclusión, se elimina únicamente ese campo en el resultado de una consulta.
Encuentre más información sobre la mecánica de proyección en el Guía de campos del proyecto que se devolverán desde la consulta en la documentación del servidor MongoDB.
La Projections clase proporciona métodos de fábrica estáticos para todos los operadores de proyección de MongoDB. Cada método devuelve una instancia del tipo BSON que se puede pasar a cualquier método que espere una proyección.
Tip
Documentos de muestra y ejemplos
Las siguientes secciones presentan ejemplos que ejecutan operaciones de consulta y proyección en una colección de muestra llamada projection_builders. Cada sección utiliza una variable llamada collection para referirse a la instancia MongoCollection de la colección projection_builders.
La colección contiene los siguientes documentos, que representan las temperaturas medias mensuales en grados Celsius para los años 2018 y 2019:
{ "year" : 2018, "type" : "even number but not a leap year", "temperatures" : [ { "month" : "January", "avg" : 9.765 }, { "month" : "February", "avg" : 9.675 }, { "month" : "March", "avg" : 10.004 }, { "month" : "April", "avg" : 9.983 }, { "month" : "May", "avg" : 9.747 }, { "month" : "June", "avg" : 9.65 }, { "month" : "July", "avg" : 9.786 }, { "month" : "August", "avg" : 9.617 }, { "month" : "September", "avg" : 9.51 }, { "month" : "October", "avg" : 10.042 }, { "month" : "November", "avg" : 9.452 }, { "month" : "December", "avg" : 9.86 } ] }, { "year" : 2019, "type" : "odd number, can't be a leap year", "temperatures" : [ { "month" : "January", "avg" : 10.023 }, { "month" : "February", "avg" : 9.808 }, { "month" : "March", "avg" : 10.43 }, { "month" : "April", "avg" : 10.175 }, { "month" : "May", "avg" : 9.648 }, { "month" : "June", "avg" : 9.686 }, { "month" : "July", "avg" : 9.794 }, { "month" : "August", "avg" : 9.741 }, { "month" : "September", "avg" : 9.84 }, { "month" : "October", "avg" : 10.15 }, { "month" : "November", "avg" : 9.84 }, { "month" : "December", "avg" : 10.366 } ] }
La siguiente clase de datos se utiliza para representar los documentos de la colección:
data class YearlyTemperature( val id: ObjectId, val year: Int, val type: String, val temperatures: List<MonthlyTemperature> ) { data class MonthlyTemperature( val month: String, val avg: Double ) }
Tip
Métodos de construcción y propiedades de la clase de datos
Puedes usar los métodos de las clases de constructor directamente con las propiedades de las clases de datos añadiendo la dependencia opcional de extensiones del controlador Kotlin a tu aplicación. Para obtener más información y ver ejemplos, consulta la guía "Usar constructores con clases de datos".
Operaciones de proyección
Las siguientes secciones contienen información sobre las operaciones de proyección disponibles y cómo construirlas utilizando la clase Projections.
Inclusión
Utilice el método include() para especificar la inclusión de uno o más campos.
El siguiente ejemplo incluye el campo year e implícitamente el campo _id:
data class Results( val id: ObjectId, val year: Int) val filter = Filters.empty() val projection = Projections.include(YearlyTemperature::year.name) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(id=6467808db5003e6354a1ee22, year=2018) Results(id=6467808db5003e6354a1ee23, year=2019)
El siguiente ejemplo incluye los campos year y type e implícitamente el campo _id:
data class Results( val id: ObjectId, val year: Int, val type: String) val filter = Filters.empty() val projection = Projections.include(YearlyTemperature::year.name, YearlyTemperature::type.name) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(id=646780e3311323724f69a907, year=2018, type=even number but not a leap year) Results(id=646780e3311323724f69a908, year=2019, type=odd number, can't be a leap year)
Exclusion
Utilice el método exclude() para especificar la exclusión de uno o más campos.
El siguiente ejemplo excluye el campo temperatures:
data class Results( val id: ObjectId, val year: Int, val type: String) val filter = Filters.empty() val projection = Projections.exclude(YearlyTemperature::temperatures.name) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(id=6462976102c85b29a7bfc9d5, year=2018, type=even number but not a leap year) Results(id=6462976102c85b29a7bfc9d6, year=2019, type=odd number, can't be a leap year)
El siguiente ejemplo excluye los campos temperatures y type:
data class Results( val id: ObjectId, val year: Int) val filter = Filters.empty() val projection = Projections.exclude(YearlyTemperature::temperatures.name, YearlyTemperature::type.name) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(id=64629783d7760d2365215147, year=2018) Results(id=64629783d7760d2365215148, year=2019)
Combinando proyecciones
Utilice el método fields() para combinar múltiples proyecciones.
El siguiente ejemplo incluye los campos year y type y excluye el campo _id:
data class Results(val year: Int, val type: String) val filter = Filters.empty() val projection = Projections.fields( Projections.include(YearlyTemperature::year.name, YearlyTemperature::type.name), Projections.excludeId() ) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(year=2018, type=even number but not a leap year) Results(year=2019, type=odd number, can't be a leap year)
Exclusión de _id
Utilice el método de conveniencia excludeId() para especificar la exclusión del campo _id:
data class Results(val year: Int, val type: String, val temperatures: List<YearlyTemperature.MonthlyTemperature>) val filter = Filters.empty() val projection = Projections.excludeId() val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(year=2018, type=even number but not a leap year, temperatures=[MonthlyTemperature(month=January, avg=9.765), MonthlyTemperature(month=February, avg=9.675), MonthlyTemperature(month=March, avg=10.004), MonthlyTemperature(month=April, avg=9.983), MonthlyTemperature(month=May, avg=9.747), MonthlyTemperature(month=June, avg=9.65), MonthlyTemperature(month=July, avg=9.786), MonthlyTemperature(month=August, avg=9.617), MonthlyTemperature(month=September, avg=9.51), MonthlyTemperature(month=October, avg=10.042), MonthlyTemperature(month=November, avg=9.452), MonthlyTemperature(month=December, avg=9.86)]) Results(year=2019, type=odd number, can't be a leap year, temperatures=[MonthlyTemperature(month=January, avg=10.023), MonthlyTemperature(month=February, avg=9.808), MonthlyTemperature(month=March, avg=10.43), MonthlyTemperature(month=April, avg=10.175), MonthlyTemperature(month=May, avg=9.648), MonthlyTemperature(month=June, avg=9.686), MonthlyTemperature(month=July, avg=9.794), MonthlyTemperature(month=August, avg=9.741), MonthlyTemperature(month=September, avg=9.84), MonthlyTemperature(month=October, avg=10.15), MonthlyTemperature(month=November, avg=9.84), MonthlyTemperature(month=December, avg=10.366)])
Proyectar una coincidencia de elementos de matriz
Utilice la elemMatch(String, Bson) variante del método para especificar una proyección de matriz que incluirá el primer elemento de una matriz que coincida con el filtro de consulta proporcionado. Este filtrado se realiza después de recuperar todos los documentos que coinciden con el filtro de consulta (si se proporciona).
Nota
Solo se incluirá el primer elemento que coincida con el filtro de consulta especificado, independientemente de cuántas coincidencias pueda haber.
El siguiente ejemplo proyecta el primer elemento de la matriz temperatures donde el campo avg es mayor que 10.1:
data class Results( val year: Int, val temperatures: List<YearlyTemperature.MonthlyTemperature>? ) val filter = Filters.empty() val projection = Projections.fields( Projections.include(YearlyTemperature::year.name), Projections.elemMatch( YearlyTemperature::temperatures.name, Filters.gt(YearlyTemperature.MonthlyTemperature::avg.name, 10.1) ) ) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(year=2018, temperatures=null) Results(year=2019, temperatures=[MonthlyTemperature(month=March, avg=10.43)])
Una vez especificados los criterios de coincidencia en la consulta, utilice la elemMatch(String) variante del método para especificar una proyección posicional que incluya el primer elemento de una matriz. Solo se recuperarán los documentos que coincidan con el filtro de consulta.
Importante
En versiones de MongoDB anteriores a la 4.4, el campo de arreglo especificado debe aparecer en el filtro de query. A partir de MongoDB 4.4, puedes utilizar un Proyecto posicional en un campo de arreglo que no aparece en el filtro de query.
El siguiente ejemplo proyecta el primer elemento de la matriz temperatures:
data class Results( val year: Int, val temperatures: List<YearlyTemperature.MonthlyTemperature> ) val filter = Filters.gt( "${YearlyTemperature::temperatures.name}.${YearlyTemperature.MonthlyTemperature::avg.name}", 10.1 ) val projection = Projections.fields( Projections.include(YearlyTemperature::year.name), Projections.elemMatch(YearlyTemperature::temperatures.name) ) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(year=2019, temperatures=[MonthlyTemperature(month=March, avg=10.43)])
Proyectar una porción de arreglo
Utilice el slice() método para proyectar una porción de una matriz.
El siguiente ejemplo proyecta los primeros 6 elementos de la matriz temperatures:
data class Results(val temperatures: List<YearlyTemperature.MonthlyTemperature>) val filter = Filters.empty() // First half of the year val projection = Projections.fields( Projections.slice(YearlyTemperature::temperatures.name, 6), Projections.excludeId() ) val resultsFlow = collection.find<Results>(filter) .projection(projection) resultsFlow.collect { println(it) }
Results(temperatures=[MonthlyTemperature(month=January, avg=9.765), MonthlyTemperature(month=February, avg=9.675), MonthlyTemperature(month=March, avg=10.004), MonthlyTemperature(month=April, avg=9.983), MonthlyTemperature(month=May, avg=9.747), MonthlyTemperature(month=June, avg=9.65)]) Results(temperatures=[MonthlyTemperature(month=January, avg=10.023), MonthlyTemperature(month=February, avg=9.808), MonthlyTemperature(month=March, avg=10.43), MonthlyTemperature(month=April, avg=10.175), MonthlyTemperature(month=May, avg=9.648), MonthlyTemperature(month=June, avg=9.686)])
El siguiente ejemplo omite los primeros 6 elementos de la temperatures matriz y proyecta 6 los siguientes:
data class Results(val temperatures: List<YearlyTemperature.MonthlyTemperature>) val filter = Filters.empty() // Second half of the year val projection = Projections.fields( Projections.slice(YearlyTemperature::temperatures.name, 6, 6), Projections.excludeId() ) val resultsFlow = collection.find<Results>(filter) .projection(projection) resultsFlow.collect { println(it) }
Results(temperatures=[MonthlyTemperature(month=July, avg=9.786), MonthlyTemperature(month=August, avg=9.617), MonthlyTemperature(month=September, avg=9.51), MonthlyTemperature(month=October, avg=10.042), MonthlyTemperature(month=November, avg=9.452), MonthlyTemperature(month=December, avg=9.86)]) Results(temperatures=[MonthlyTemperature(month=July, avg=9.794), MonthlyTemperature(month=August, avg=9.741), MonthlyTemperature(month=September, avg=9.84), MonthlyTemperature(month=October, avg=10.15), MonthlyTemperature(month=November, avg=9.84), MonthlyTemperature(month=December, avg=10.366)])
Proyectar una partitura de texto
Utilice el metaTextScore() método para especificar una proyección de la puntuación de una consulta de texto.
El siguiente ejemplo proyecta la puntuación de texto como el valor del campo score:
data class Results(val year: Int, val score: Double) val filter = Filters.text("even number") val projection = Projections.fields( Projections.include(YearlyTemperature::year.name), Projections.metaTextScore("score") ) val resultsFlow = collection.find<Results>(filter).projection(projection) resultsFlow.collect { println(it) }
Results(year=2018, score=1.25) Results(year=2019, score=0.625)