Referencing nested array fields in typed Mongo
Assuming a hierarchy like this:
case class InnerRecord(
int: Int,
str: String,
)
object InnerRecord extends MongoDataCompanion[InnerRecord]
case class RecordTestEntity(
id: String,
innerList: List[InnerRecord]
) extends MongoEntity[String]
object RecordTestEntity extends MongoEntityCompanion[RecordTestEntity]
How can I construct a projection so that only innerList.int fields are returned? I know I can reference the fields at particular index of the list, eg. RecordTestEntity.ref(_.innerList.head.int), but I would like to achieve something like this: RecordTestEntity.ref(_.innerList.map(_.int)). Is it possible?
Hi, I'm not aware of any MongoDB projection operator that would do this (please let me know if you find one). Assuming that there is no such operator in MongoDB API itself, you have two options:
- Map the projection itself in runtime, i.e.
RecordTestEntity.ref(_.innerList).map(_.map(_.int))- the mapping will happen on the client side, MongoDB will not be aware of it and will be sending full objects on the wire. Note that this is largely equivalent to mapping theObservablereturned byTypedMongoCollection.find(). - Use the Aggregation Framework - you will need to use the native API of the ReactiveStreams driver as it is not covered by AVSystem's Typed Mongo API
Just specifying the path to the field inside array (innerList.int) works for me using Compass/MongoDB shell. https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/#projection-on-embedded-documents-in-an-array - the syntax is described here.
Oh, nice, I didn't know about that. We will add support for it.
@AvaPL FYI: I hoped to do this quickly but it turned out to be somewhat annoying, mostly because of binary compatibility issues. We're still planning to do this one way or another.
No pressure, thank you for the information.
There's another use-case for innerList.int path, i.e. it can be used to filter documents by inner field value as described here: https://www.mongodb.com/docs/manual/tutorial/query-array-of-documents/#specify-a-query-condition-on-a-field-in-an-array-of-documents. It would be nice if it was somehow supported by the driver.
Currently we do this kind of workaround, which works for queries and indexes, but it probably fails for updates.
final val InnerIntRef: Ref[Int] = FieldRef(ref(_.innerList), "int", implicitly, Opt.Empty)