@@ -3,40 +3,17 @@ package no.java.conf.service
3
3
import arrow.core.raise.Raise
4
4
import arrow.core.raise.ensure
5
5
import arrow.core.raise.ensureNotNull
6
- import com.jillesvangurp.jsondsl.json
7
- import com.jillesvangurp.ktsearch.Aggregations
8
- import com.jillesvangurp.ktsearch.SearchClient
9
- import com.jillesvangurp.ktsearch.count
10
- import com.jillesvangurp.ktsearch.parseHits
11
- import com.jillesvangurp.ktsearch.parsedBuckets
12
- import com.jillesvangurp.ktsearch.search
13
- import com.jillesvangurp.ktsearch.termsResult
14
- import com.jillesvangurp.searchdsls.querydsl.SearchDSL
15
- import com.jillesvangurp.searchdsls.querydsl.TermsAgg
16
- import com.jillesvangurp.searchdsls.querydsl.agg
17
- import com.jillesvangurp.searchdsls.querydsl.bool
18
- import com.jillesvangurp.searchdsls.querydsl.exists
19
- import com.jillesvangurp.searchdsls.querydsl.nested
20
- import com.jillesvangurp.searchdsls.querydsl.simpleQueryString
21
- import com.jillesvangurp.searchdsls.querydsl.terms
22
6
import io.github.oshai.kotlinlogging.KotlinLogging
23
- import no.java.conf.model.AggregationsNotFound
24
7
import no.java.conf.model.ApiError
25
8
import no.java.conf.model.IndexNotReady
26
9
import no.java.conf.model.SearchMissing
27
- import no.java.conf.model.search.AggregateResponse
28
- import no.java.conf.model.search.FormatAggregate
29
- import no.java.conf.model.search.LanguageAggregate
30
10
import no.java.conf.model.search.SearchResponse
31
- import no.java.conf.model.search.SessionResponse
32
11
import no.java.conf.model.search.TextSearchRequest
33
12
import no.java.conf.model.search.VideoSearchResponse
34
- import no.java.conf.model.search.YearAggregate
35
- import no.java.conf.model.search.hasFilter
36
- import no.java.conf.model.search.hasQuery
37
13
import no.java.conf.model.sessions.Session
38
14
import no.java.conf.service.search.ElasticIndexer
39
15
import no.java.conf.service.search.ElasticIngester
16
+ import no.java.conf.service.search.ElasticSearcher
40
17
import kotlin.time.measureTimedValue
41
18
42
19
private const val INDEX_NAME = " javazone"
@@ -50,9 +27,9 @@ enum class State {
50
27
}
51
28
52
29
class SearchService (
53
- private val client : SearchClient ,
54
30
private val indexer : ElasticIndexer ,
55
31
private val ingester : ElasticIngester ,
32
+ private val searcher : ElasticSearcher ,
56
33
private val skipIndex : Boolean ,
57
34
) {
58
35
private var readyState = State .NEW
@@ -105,15 +82,7 @@ class SearchService(
105
82
suspend fun allVideos (): List <VideoSearchResponse > {
106
83
ensureReady(readyState)
107
84
108
- val docCount = client.totalDocs()
109
-
110
- val sessions =
111
- client.search(INDEX_NAME ) {
112
- resultSize = docCount.toInt()
113
- query = exists(" video" )
114
- }
115
-
116
- return sessions.parseHits<VideoSearchResponse >().sortedBy { - it.year }
85
+ return searcher.allVideos(INDEX_NAME )
117
86
}
118
87
119
88
fun state (): State = readyState
@@ -126,27 +95,7 @@ class SearchService(
126
95
127
96
ensureReady(readyState)
128
97
129
- val docCount = client.totalDocs()
130
-
131
- val searchResult =
132
- client.search(INDEX_NAME ) {
133
- addQuery(docCount, searchRequest)
134
-
135
- addLanguageAggregate(docCount)
136
- addFormatAggregate(docCount)
137
- addYearAggregate(docCount)
138
-
139
- logger.debug { this .json() }
140
- }
141
-
142
- ensure(searchResult.aggregations != null ) {
143
- raise(AggregationsNotFound )
144
- }
145
-
146
- return SearchResponse (
147
- searchResult.parseHits<SessionResponse >().sortedBy { - it.year },
148
- searchResult.aggregations!! .buildResponse()
149
- )
98
+ return searcher.textSearch(INDEX_NAME , searchRequest)
150
99
}
151
100
}
152
101
@@ -155,119 +104,3 @@ private fun Raise<ApiError>.ensureReady(readyState: State) {
155
104
raise(IndexNotReady )
156
105
}
157
106
}
158
-
159
- private fun Aggregations.buildResponse () =
160
- AggregateResponse (
161
- languages =
162
- this
163
- .termsResult(" by-language" )
164
- .parsedBuckets
165
- .map { LanguageAggregate (it.parsed.key, it.parsed.docCount) },
166
- formats =
167
- this
168
- .termsResult(" by-format" )
169
- .parsedBuckets
170
- .map { FormatAggregate (it.parsed.key, it.parsed.docCount) },
171
- years =
172
- this
173
- .termsResult(" by-year" )
174
- .parsedBuckets
175
- .map { YearAggregate (it.parsed.key.toInt(), it.parsed.docCount) }
176
- .sortedBy { - it.year },
177
- )
178
-
179
- private fun SearchDSL.addLanguageAggregate (docCount : Long ) {
180
- this .agg(
181
- " by-language" ,
182
- TermsAgg (Session ::language.name) {
183
- aggSize = docCount
184
- minDocCount = 1
185
- }
186
- )
187
- }
188
-
189
- private fun SearchDSL.addFormatAggregate (docCount : Long ) {
190
- this .agg(
191
- " by-format" ,
192
- TermsAgg (Session ::format.name) {
193
- aggSize = docCount
194
- minDocCount = 1
195
- }
196
- )
197
- }
198
-
199
- private fun SearchDSL.addYearAggregate (docCount : Long ) {
200
- this .agg(
201
- " by-year" ,
202
- TermsAgg (Session ::year) {
203
- aggSize = docCount
204
- minDocCount = 1
205
- }
206
- )
207
- }
208
-
209
- private fun SearchDSL.addQuery (
210
- docCount : Long ,
211
- searchRequest : TextSearchRequest
212
- ) {
213
- logger.debug { " Building query for $searchRequest " }
214
-
215
- resultSize =
216
- when (! searchRequest.hasQuery() && ! searchRequest.hasFilter()) {
217
- true -> 0
218
- false -> docCount.toInt()
219
- }
220
-
221
- val queryString =
222
- when {
223
- searchRequest.hasQuery() -> searchRequest.query
224
- searchRequest.hasFilter() -> " *"
225
- else -> null
226
- }
227
-
228
- val textQuery =
229
- queryString?.let { q ->
230
- bool {
231
- should(
232
- simpleQueryString(q, " title" , " abstract" , " intendedAudience" ),
233
- nested {
234
- path = " speakers"
235
- query = simpleQueryString(q, " speakers.name" , " speakers.bio" )
236
- }
237
- )
238
- }
239
- }
240
-
241
- val yearQuery =
242
- searchRequest.years.ifEmpty { null }?.let { years ->
243
- terms(
244
- field = " year" ,
245
- values = years.map { it.toString() }.toTypedArray()
246
- )
247
- }
248
-
249
- val languageQuery =
250
- searchRequest.languages.ifEmpty { null }?.let { languages ->
251
- terms(
252
- field = " language" ,
253
- values = languages.toTypedArray()
254
- )
255
- }
256
-
257
- val formatQuery =
258
- searchRequest.formats.ifEmpty { null }?.let { formats ->
259
- terms(
260
- field = " format" ,
261
- values = formats.toTypedArray()
262
- )
263
- }
264
-
265
- this .query =
266
- bool {
267
- must(
268
- listOfNotNull(textQuery, yearQuery, languageQuery, formatQuery)
269
- )
270
- }
271
- }
272
-
273
- private suspend fun SearchClient.totalDocs () = this .count(INDEX_NAME ).count
0 commit comments