Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Referencing nested array fields in typed Mongo #422

Open
AvaPL opened this issue Jul 20, 2022 · 6 comments
Open

Referencing nested array fields in typed Mongo #422

AvaPL opened this issue Jul 20, 2022 · 6 comments

Comments

@AvaPL
Copy link

AvaPL commented Jul 20, 2022

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
Copy link
Contributor

ghik commented Jul 20, 2022

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 the Observable returned by TypedMongoCollection.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

@AvaPL
Copy link
Author

AvaPL commented Jul 20, 2022

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
Copy link
Contributor

ghik commented Jul 20, 2022

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

@ghik
Copy link
Contributor

ghik commented Aug 24, 2022

@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
Copy link
Author

AvaPL commented Aug 24, 2022

No pressure, thank you for the information.

@enthyp
Copy link

enthyp commented Jan 2, 2023

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants