AVSystem / scala-commons

AVSystem commons library for Scala
http://www.avsystem.com
MIT License
86 stars 20 forks source link

Referencing nested array fields in typed Mongo #422

Open AvaPL opened 2 years ago

AvaPL commented 2 years ago

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?

ghik commented 2 years ago

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:

AvaPL commented 2 years ago

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.

ghik commented 2 years ago

Oh, nice, I didn't know about that. We will add support for it.

ghik commented 2 years ago

@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.

AvaPL commented 2 years ago

No pressure, thank you for the information.

enthyp commented 1 year ago

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)