From 59ef80812322f7260e0189ca9b537029e870c9b1 Mon Sep 17 00:00:00 2001 From: avalin Date: Sat, 1 Jun 2024 10:53:47 +0200 Subject: [PATCH] Fix user search --- .../data/postgres/PostgresFriendDataSource.kt | 31 ++++++++++++++----- .../src/main/kotlin/allin/ext/DatabaseExt.kt | 17 +++++++--- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt index f9cb251..0577a74 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt @@ -5,7 +5,7 @@ import allin.data.postgres.entities.FriendEntity import allin.data.postgres.entities.friends import allin.data.postgres.entities.users import allin.dto.UserDTO -import allin.ext.levenshtein +import allin.ext.levenshteinLessEq import allin.ext.toLowerCase import allin.model.FriendStatus import org.ktorm.database.Database @@ -50,7 +50,7 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc } else { database.users.find { usr -> usr.id eq it.sender - }?.toUserDTO(database,friendStatus = FriendStatus.NOT_FRIEND) + }?.toUserDTO(database, friendStatus = FriendStatus.NOT_FRIEND) } } } @@ -66,10 +66,25 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc override fun isFriend(firstUser: String, secondUser: String) = database.friends.any { (it.sender eq firstUser) and (it.receiver eq secondUser) } - override fun filterUsersByUsername(fromUserId: String, search: String): List = - database.users - .filter { it.id notEq fromUserId } - .sortedBy { it.username.toLowerCase().levenshtein(search.lowercase()) } - .take(10) - .map { user -> user.toUserDTO(database,friendStatus = getFriendStatus(fromUserId, user.id)) } + override fun filterUsersByUsername(fromUserId: String, search: String): List { + val maxSize = search.length / 2 + return database.users + .filter { (it.id notEq fromUserId) } + .mapColumns { + tupleOf( + it.id, + it.username.toLowerCase().levenshteinLessEq(search.lowercase(), maxSize) + ) + } + .filter { (_, distance) -> + distance?.let { it <= maxSize } ?: false + } + .sortedBy { it.second } + .mapNotNull { (id, _) -> + id?.let { + val user = database.users.find { it.id eq id } + user?.toUserDTO(database, friendStatus = getFriendStatus(fromUserId, user.id)) + } + } + } } \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt b/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt index 085ee09..5562503 100644 --- a/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt +++ b/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt @@ -1,6 +1,7 @@ package allin.ext import org.ktorm.database.Database +import org.ktorm.expression.ArgumentExpression import org.ktorm.expression.FunctionExpression import org.ktorm.schema.ColumnDeclaring import org.ktorm.schema.IntSqlType @@ -48,13 +49,19 @@ fun ColumnDeclaring.toUpperCase(): FunctionExpression { ) } -fun ColumnDeclaring.levenshtein(target: ColumnDeclaring): FunctionExpression { +fun ColumnDeclaring.levenshteinLessEq( + target: ColumnDeclaring, + max: ColumnDeclaring +): FunctionExpression { return FunctionExpression( - functionName = "levenshtein", - arguments = listOf(this.asExpression(), target.asExpression()), + functionName = "levenshtein_less_equal", + arguments = listOf(this.asExpression(), target.asExpression(), max.asExpression()), sqlType = IntSqlType ) } -fun ColumnDeclaring.levenshtein(target: String): FunctionExpression = - levenshtein(wrapArgument(target)) \ No newline at end of file +fun ColumnDeclaring.levenshteinLessEq(target: String, max: Int): FunctionExpression = + levenshteinLessEq( + wrapArgument(target), + ArgumentExpression(max, IntSqlType) + ) \ No newline at end of file