Spring Boot Kotlin Reactive:如何将多个 MongoDB 查询的结果链接在一起以获得单个响应?

Spring Boot Kotlin Reactive: How do I link the results from multiple MongoDB queries together for a single response?

提问人:SteVio 提问时间:4/23/2018 更新时间:4/23/2018 访问量:99

问:

我现在正在尝试使用 Spring-Boot 2 Kotlin Reactive。我的一个端点应该能够将电话号码从 MongoDB 解析为个人、公司或部门。

因此,例如,对于手机,显示名称应以字符串形式返回。

可以使用请求中的参数更改结果:

http://localhost:8080/api/v1/numbers/find/xxxxxxxxxxx?asString=true&firstname=2&lastname=1&company=3&department=4

firstname、lastname、company 和 department 的值指定显示名称中的顺序。

如果“xxxxxxxxxxx”是一个人的号码,则响应应如下所示:

“姓氏、名字、公司、部门”

我已经找到了解决这个问题的方法,但我想知道是否有更好的方法。

fun findNumberOwner(serverRequest: ServerRequest) =
        numberRepository.findByNumber(serverRequest.pathVariable("number")).flatMap { n ->
            serverRequest.queryParam("asString")
                    .filter {
                        it.trim()
                                .isNotEmpty().and(it.toBoolean())
                    }
                    .map { searchNumberWithStringResult(n, serverRequest.queryParam("firstname"), serverRequest.queryParam("lastname"), serverRequest.queryParam("company"), serverRequest.queryParam("department")) }
                    .orElse(searchNumberWithJsonResult(n))
        }.switchIfEmpty(ServerResponse.notFound().build())

private fun searchNumberWithStringResult(number: Number, firstname: Optional<String>, lastname: Optional<String>, company: Optional<String>, department: Optional<String>): Mono<ServerResponse> {
    val ownerId = number.numberOwner

    if (ownerId.startsWith("CO-")) {
        return ok().body(companyRepository.findById(ownerId).map { it.name })
    } else if (ownerId.startsWith("DE-")) {
        return ok().body(departmentRepository.findById(ownerId)
                .map { dep ->
                    companyRepository.findById(dep.company)
                            .map {
                                it.name
                            }.zipWith(dep.toMono())
                }.flatMap { it ->
                    it
                }.map {
                    it.t1 + ", " + it.t2.name
                })
    } else {
        val templateMap = mapOf(
                Pair("firstname", firstname.orElse("2").toInt()),
                Pair("lastname", lastname.orElse("1").toInt()),
                Pair("company", company.orElse("0").toInt()),
                Pair("department", department.orElse("0").toInt())
        )

        return ok().body(personRepository.findById(ownerId)
                .map { person ->

                    companyRepository.findById(person.company)
                            .map {
                                it.name
                            }
                            .switchIfEmpty(Mono.just(""))
                            .zipWith(person.toMono())
                }.flatMap { it ->
                    it
                }.map { t ->
                    departmentRepository.findById(t.t2.department).map {
                        mapOf(
                                Pair(templateMap["firstname"], t.t2.firstName) as Pair<Int, String>,
                                Pair(templateMap["lastname"], t.t2.lastName) as Pair<Int, String>,
                                Pair(templateMap["company"], t.t1) as Pair<Int, String>,
                                Pair(templateMap["department"], it.name) as Pair<Int, String>)
                                .filter { it.key > 0 }.filter { !it.value.equals("") }.toSortedMap()
                    }
                            .switchIfEmpty(Mono.just(
                                    mapOf(
                                            Pair(templateMap["firstname"], t.t2.firstName) as Pair<Int, String>,
                                            Pair(templateMap["lastname"], t.t2.lastName) as Pair<Int, String>,
                                            Pair(templateMap["company"], t.t1) as Pair<Int, String>)
                                            .filter { it.key > 0 }.filter { !it.value.equals("") }.toSortedMap()
                            ))
                }.flatMap { it -> it }
                .map { it }
                .map { myMap ->
                    var finalDisplayString = ""
                    myMap.forEach {
                        finalDisplayString += buildDisplayString(it.key, myMap.size, it.value)
                    }
                    finalDisplayString
                })
    }
}

private fun buildDisplayString(index: Int, maxSize: Int, value: String?): String {
    if (value == null) return ""
    if (index == 0) {
        return "$value, "
    } else if (index == maxSize) {
        return "$value"
    } else {
        return "$value, "
    }
}
Spring MongoDB spring-Boot Kotlin 响应式编程

评论

0赞 caeus 4/23/2018
map{it}什么都不做。与其后跟一个,不如做一个mapflatMap{it->it}flatMap

答: 暂无答案