https://kotlinlang.org logo
#apollo-kotlin
Title
# apollo-kotlin
n

Nick

07/08/2022, 8:53 PM
There's a bug on our backend that's making me do two graphql queries get get all the data needed for list of objects. Query 1: Gives me an ID (and some other info) Query 2: Use ID to get additional data I'd like to be able to
watch
for cache changes from both queries, but I end up with a
Flow<List<Flow<MyObject>>>
. I'd much rather have a
Flow<List<MyObject>>
. Code in 🧵
Copy code
apollo.query(LabReportsByPatientQuery(recordStoreId))
    .fetchPolicy(fetchPolicy)
    .watch()
    .mapNotNull { it: ApolloResponse<LabReportsByPatientQuery.Data> ->
        it.dataAssertNoErrors.patient.diagnosticReportSubject.edgesFilterNotNull()
            ?.map { edge ->
                edge.node
            }
    }
    .map { nodes: List<LabReportsByPatientQuery.Node> ->
        nodes
            .mapNotNull { node ->
                try {
                    apollo.query(LabResultByIdQuery("DiagnosticReport/${node.labResultFragment.id}"))
                        .fetchPolicy(fetchPolicy)
                        .watch()
                        .map {  ... convert to lab result }
                } catch (ex: Exception) {
                    // If there's an error translating the data to a lab result, return null so its skipped
                    null
                }
            }
    }
// This flow is a Flow<List<Flow<ApolloResponse<LabResultByIdQuery.Data>>>>
w

wasyl

07/08/2022, 10:12 PM
I only glanced at your code, but generally what you want is solved with a
flatMap
n

Nick

07/08/2022, 10:13 PM
Thanks, i tried that, but since the nodes is a
list
,
flatMap
won't work in this situation.
b

bod

07/09/2022, 7:49 AM
maybe something like this
Copy code
suspend fun <T> Flow<List<Flow<T>>>.donkey(): Flow<T> = flow {
    collect {
      for (subFlow: Flow<T> in it) {
        emitAll(subFlow)
      }
    }
  }
❤️ 1
e

ephemient

07/09/2022, 7:51 AM
I think it's more likely Nick wants something like
Copy code
.flatMap { nodes: List<LabReportsByPatientQuery.Node> ->
        combine(
            nodes.mapNotNull { node ->
                try {
                    apollo.query(LabResultByIdQuery("DiagnosticReport/${node.labResultFragment.id}"))
                        .fetchPolicy(fetchPolicy)
                        .watch()
                        .map {  ... convert to lab result }
                } catch (ex: Exception) {
                    // If there's an error translating the data to a lab result, return null so its skipped
                    null
                }
            }
        ) { it.toList() }
    }
this should result in a
Flow<List<ApolloResponse<LabResultByIdQuery.Data>>>
where each list is
nodes.size
in size and contains one element from each inner flow
❤️ 1
but what kind of backend bug? GraphQL is supposed to mean you don't need to do this kind of multi-request merging on the client
n

Nick

07/11/2022, 4:33 PM
Agreed. There's something called a Task, and when I include it in the query, it returns an empty array. When I do a search using the ID, I am able to get it.
Thanks for your help guys 🙂
3 Views