Skip to content

Commit

Permalink
#17 add elasticsearch search handle
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillsinyuk committed Feb 17, 2024
1 parent bbe2c1e commit 659029c
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 10 deletions.
3 changes: 3 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
:imagesdir: ./docs
MongoDb + Elasticsearch
------------------------

Expand All @@ -21,3 +22,5 @@ How?
It brought me to the idea that I could use another database that was made for text search.
The main problem was how to sync the data between them.
And this is where https://rwynn.github.io/monstache-site/[Monstache^] takes action.

image::schema.png[width=500]
Binary file added docs/schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kvsinyuk.elasticsearch.adapter.`in`.http

import com.kvsinyuk.elasticsearch.application.port.SearchDealsUseCase
import com.kvsinyuk.elasticsearch.domain.Deal
import mu.KLogging
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
class DealController(
private val searchDealsUseCase: SearchDealsUseCase
) {

@GetMapping("/deals")
fun generateRandomData(@RequestParam search: String, pageable: Pageable): Page<Deal> {
logger.info { "Received request for search deals with $search" }
return searchDealsUseCase.searchDeals(search, pageable)
}

companion object: KLogging()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.kvsinyuk.elasticsearch.adapter.out.elasticsearch

import com.kvsinyuk.elasticsearch.domain.Deal
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.elasticsearch.annotations.Query
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository

interface ElasticDealRepository : ElasticsearchRepository<Deal, String> {

@Query(query = "{ \"multi_match\" : {\"query\" : \"?0\" }}")
//@Query(query = "\"query\": {\"bool\": {\"must\": [{ \"match\": {\"userId\": ?0}}]}}")
fun searchAll(search: String, page: Pageable): Page<Deal>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ import com.kvsinyuk.elasticsearch.domain.Deal
import org.bson.types.ObjectId
import org.springframework.data.mongodb.repository.MongoRepository

interface DealRepository : MongoRepository<Deal, ObjectId>
interface MongoDealRepository : MongoRepository<Deal, ObjectId>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.kvsinyuk.elasticsearch.application.impl

import com.kvsinyuk.elasticsearch.adapter.out.mongo.DealRepository
import com.kvsinyuk.elasticsearch.adapter.out.mongo.MongoDealRepository
import com.kvsinyuk.elasticsearch.application.port.GenerateDealsUseCase
import com.kvsinyuk.elasticsearch.utils.generateDeal
import kotlinx.coroutines.CoroutineScope
Expand All @@ -11,14 +11,14 @@ import org.springframework.stereotype.Component

@Component
class GenerateDealsUseCaseImpl(
private val dealRepository: DealRepository
private val dealRepository: MongoDealRepository
): GenerateDealsUseCase {

@Value("\${generator.batch.count}")
private var batchCount: Int = 20

override fun generateDeals(dealAmount: Int) {
for (i in dealAmount downTo batchCount) {
for (i in dealAmount downTo 0 step batchCount) {
CoroutineScope(Dispatchers.Default).launch {
(0 until batchCount)
.map { generateDeal() }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.kvsinyuk.elasticsearch.application.impl

import com.kvsinyuk.elasticsearch.adapter.out.elasticsearch.ElasticDealRepository
import com.kvsinyuk.elasticsearch.application.port.SearchDealsUseCase
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Component

@Component
class SearchDealsUseCaseImpl(
private val dealRepository: ElasticDealRepository
): SearchDealsUseCase {

override fun searchDeals(search: String, page: Pageable) =
dealRepository.searchAll(search, page)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.kvsinyuk.elasticsearch.application.port

import com.kvsinyuk.elasticsearch.domain.Deal
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable

interface SearchDealsUseCase {

fun searchDeals(search: String, page: Pageable): Page<Deal>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.kvsinyuk.elasticsearch.config

import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories

@Configuration
@EnableElasticsearchRepositories(basePackages = ["com.kvsinyuk.elasticsearch.adapter.out.elasticsearch"])
@ComponentScan(basePackages = [ "com.kvsinyuk.elasticsearch" ])
class ElasticsearchConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.kvsinyuk.elasticsearch.config

import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.config.EnableMongoAuditing
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories

@Configuration
@EnableMongoAuditing
@EnableMongoRepositories(basePackages = ["com.kvsinyuk.elasticsearch.adapter.out.mongo"])
@ComponentScan(basePackages = [ "com.kvsinyuk.elasticsearch" ])
class MongoConfiguration
8 changes: 5 additions & 3 deletions src/main/kotlin/com/kvsinyuk/elasticsearch/domain/Deal.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ package com.kvsinyuk.elasticsearch.domain

import org.bson.types.ObjectId
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.mapping.Document
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime

@Document
@org.springframework.data.elasticsearch.annotations.Document(indexName = "order.deal")
class Deal {

@Id
lateinit var id: ObjectId

lateinit var number: String

lateinit var date: LocalDate
lateinit var date: LocalDateTime

var sellers: List<Seller> = emptyList()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import com.kvsinyuk.elasticsearch.domain.Deal
import com.kvsinyuk.elasticsearch.domain.Guarantor
import com.kvsinyuk.elasticsearch.domain.Name
import com.kvsinyuk.elasticsearch.domain.Seller
import java.time.LocalDate
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.concurrent.ThreadLocalRandom

fun generateDeal(): Deal {
return Deal()
.apply {
number = dealNumberPatternGenerator.generate()
date = LocalDate.ofEpochDay(ThreadLocalRandom.current().nextLong(-hundredYears, hundredYears))
date = LocalDateTime.ofInstant(Instant.ofEpochSecond(ThreadLocalRandom.current().nextLong(-hundredYears, hundredYears)), ZoneId.systemDefault())
sellers = createRandomSellers((0 until 10).random())
buyers = createRandomBuyer((0 until 10).random())
guarantors = createRandomGuarantors((0 until 3).random())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,27 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnect
import org.springframework.boot.with
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.MongoDBContainer
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy
import org.testcontainers.elasticsearch.ElasticsearchContainer
import org.testcontainers.utility.DockerImageName
import java.time.Duration

@TestConfiguration(proxyBeanMethods = false)
class TestElasticsearchApplication {

@Bean
@ServiceConnection
fun elasticsearchContainer(): ElasticsearchContainer {
return ElasticsearchContainer(DockerImageName.parse("bitnami/elasticsearch:latest"))
return ElasticsearchContainer(
DockerImageName.parse("bitnami/elasticsearch:latest")
.asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch")
)
.also {
it.setWaitStrategy(
LogMessageWaitStrategy()
.withRegEx(".*started.*").withStartupTimeout(Duration.ofMinutes(3))
)
}
}

@Bean
Expand Down

0 comments on commit 659029c

Please sign in to comment.