投影构建器
Overview
在本指南中,您可以学习;了解如何在MongoDB Kotlin驾驶员中使用 构建者 指定 投影 。
MongoDB 支持字段投影,可指定在返回查询结果时包含和排除哪些字段。MongoDB 中的投影遵循一些基本规则:
除非明确排除,否则
_id
字段始终包含在内指定要包含的字段将隐式排除
_id
字段以外的所有其他字段指定排除字段只会删除查询结果中的该字段
有关投影机制的更多信息,请参阅MongoDB Server文档中的“从查询中指南的项目字段”指南。
Projections
类为所有 MongoDB 投影操作符提供静态工厂方法。每个方法都返回一个 BSON 类型的实例,您可以将其传递给任何需要投影的方法。
提示
为了简洁起见,您可以选择导入 Projections 的方法 class:
import com.mongodb.client.model.Projections.*
样本文档和示例
以下部分介绍了对名为projection_builders
的示例集合运行查询和投影操作的示例。每个部分都使用一个名为 collection
的变量来引用 projection_builders
集合的MongoCollection
实例。
该集合包含以下文档,代表了 2018 年和 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 } ] }
以下数据类用于表示collection中的文档:
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 ) }
投影操作
以下各节包含可用投影操作以及使用Projections
类构建这些操作的相关信息。
包含
使用 include()
方法指定包含一个或多个字段。
以下示例包括year
字段和隐式_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)
以下示例包括year
和type
字段以及隐式的_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
使用 exclude()
方法指定排除一个或多个字段。
以下示例排除了 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)
以下示例排除了temperatures
和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)
合并投影
使用 fields()
方法合并多个投影。
以下示例包括 year
和 type
字段,不包括 _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)
排除 _id
使用 excludeId()
便捷方法指定排除 _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)])
投影数组元素匹配
使用elemMatch(String, Bson)
方法变体指定一个数组投影,该投影将包含与所提供的查询过滤器匹配的数组的第一个元素。在检索到与查询过滤器(如提供)匹配的所有文档后,会发生此过滤。
注意
无论有多少个匹配项,都只会包含与指定查询筛选器匹配的第一个元素。
以下示例投影 temperatures
数组的第一个元素,其中 avg
字段大于 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)])
在操作的查询部分指定匹配条件后,使用 elemMatch(String)
方法变体指定位置投影以包含数组的第一个元素。只有与查询过滤器匹配的文档才会被检索。
重要
在 MongoDB 4.4 及更早版本中,指定的数组字段必须出现在查询筛选器中。 从 MongoDB 4.4 开始,您可以对未出现在查询筛选器中的数组字段使用位置项目。
以下示例投影 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)])
投影数组切片
使用 slice()
方法投影数组片段。
以下示例项目temperatures
数组的前 6 个元素:
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)])
以下示例跳过temperatures
数组的前 6 个元素并项目后6个元素:
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)])
投影文本分数
使用metaTextScore()
方法指定文本查询分数的投影。
以下示例将文本得分投影为 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)