Skip to content

Commit 03a02bc

Browse files
committed
docs(modelql): documentation of .zip, .mapLocal and .mapLocal2
1 parent 0fc44f9 commit 03a02bc

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

docs/global/modules/core/pages/howto/modelql.adoc

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,81 @@ val cls: ClassConcept = client.query {
6565
}
6666
val className = cls.name
6767
--
68+
69+
== Complex query results
70+
71+
While returning a list of elements is simple
72+
the purpose of the query language is to reduce the number of request to a minimum.
73+
This requires to combine multiple values into more complex data structures.
74+
The `zip` operation provides a simple way of doing that:
75+
76+
[source,kotlin]
77+
--
78+
val result: List<IZip3Output<Any, Int, String, List<String>>> = query { db ->
79+
db.products.map {
80+
val id = it.id
81+
val title = it.title
82+
val images = it.images.toList()
83+
id.zip(title, images)
84+
}.toList()
85+
}
86+
result.forEach { println("ID: ${it.first}, Title: ${it.second}, Images: ${it.third}") }
87+
--
88+
89+
This is suitable for combining a small number of values,
90+
but because of the missing variable names it can be hard to read for a larger number of values
91+
or even multiple zip operations assembled into a hierarchical data structure.
92+
93+
This can be solved by defining custom data classes and using the `mapLocal` operation:
94+
95+
[source,kotlin]
96+
--
97+
data class MyProduct(val id: Int, val title: String, val images: List<MyImage>)
98+
data class MyImage(val url: String)
99+
100+
val result: List<MyNonSerializableClass> = remoteProductDatabaseQuery { db ->
101+
db.products.map {
102+
val id = it.id
103+
val title = it.title
104+
val images = it.images.mapLocal { MyImage(it) }.toList()
105+
id.zip(title, images).mapLocal {
106+
MyProduct(it.first, it.second, it.third)
107+
}
108+
}.toList()
109+
}
110+
result.forEach { println("ID: ${it.id}, Title: ${it.title}, Images: ${it.images}") }
111+
--
112+
113+
The `mapLocal` operation is not just useful in combination with the `zip` operation,
114+
but in general to create instances of classes only known to the client.
115+
116+
The body of `mapLocal` is executed on the client after receiving the result from the server.
117+
That's why you only have access to the output of the `zip` operation
118+
and still have to use `first`, `second` and `third` inside the query.
119+
120+
To make this even more readable there is a `mapLocal2` operation,
121+
which provides a different syntax for the `zip`-`mapLocal` chain.
122+
123+
[source,kotlin]
124+
--
125+
data class MyProduct(val id: Int, val title: String, val images: List<MyImage>)
126+
data class MyImage(val url: String)
127+
128+
val result: List<MyNonSerializableClass> = query { db ->
129+
db.products.mapLocal2 {
130+
val id = it.id.request()
131+
val title = it.title.request()
132+
val images = it.images.mapLocal { MyImage(it) }.toList().request()
133+
onSuccess {
134+
MyNonSerializableClass(id.get(), title.get(), images.get())
135+
}
136+
}.toList()
137+
}
138+
result.forEach { println("ID: ${it.id}, Title: ${it.title}, Images: ${it.images}") }
139+
--
140+
141+
At the beginning of the `mapLocal2` body you invoke `request()` on all the values you need to assemble your object.
142+
This basically ads the operand to the internal `zip` operation and returns an object that gives you access to the value
143+
after receiving it from the server.
144+
Inside the `onSuccess` block you assemble the local object using the previously requested values.
145+

0 commit comments

Comments
 (0)