From 95184858da10539f8c8a7974c13839eb8e44df3f Mon Sep 17 00:00:00 2001 From: avalin Date: Tue, 28 May 2024 11:22:16 +0200 Subject: [PATCH] Add fuzzy user search with levenshtein --- .../allin/data/postgres/PostgresDataSource.kt | 6 ++++++ .../data/postgres/PostgresFriendDataSource.kt | 6 ++++-- Sources/src/main/kotlin/allin/ext/DatabaseExt.kt | 14 +++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Sources/src/main/kotlin/allin/data/postgres/PostgresDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresDataSource.kt index 705750d..12e2f11 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresDataSource.kt @@ -25,6 +25,12 @@ class PostgresDataSource : AllInDataSource() { dialect = PostgreSqlDialect() ) + database.execute( + """ + CREATE EXTENSION IF not exists fuzzystrmatch; + """.trimIndent() + ) + database.execute( """ CREATE TABLE IF not exists users ( diff --git a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt index ce78345..4c2eefd 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt @@ -5,12 +5,12 @@ 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.toLowerCase import allin.model.FriendStatus import org.ktorm.database.Database import org.ktorm.dsl.and import org.ktorm.dsl.eq -import org.ktorm.dsl.like import org.ktorm.dsl.notEq import org.ktorm.entity.* @@ -48,6 +48,8 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc override fun filterUsersByUsername(fromUserId: String, search: String): List = database.users - .filter { (it.username.toLowerCase() like "%$search%") and (it.id notEq fromUserId) } + .filter { it.id notEq fromUserId } + .sortedBy { it.username.toLowerCase().levenshtein(search.lowercase()) } + .take(10) .map { user -> user.toUserDTO(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 3a5bd61..085ee09 100644 --- a/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt +++ b/Sources/src/main/kotlin/allin/ext/DatabaseExt.kt @@ -3,6 +3,7 @@ package allin.ext import org.ktorm.database.Database import org.ktorm.expression.FunctionExpression import org.ktorm.schema.ColumnDeclaring +import org.ktorm.schema.IntSqlType import org.ktorm.schema.VarcharSqlType import java.sql.ResultSet @@ -45,4 +46,15 @@ fun ColumnDeclaring.toUpperCase(): FunctionExpression { arguments = listOf(this.asExpression()), sqlType = VarcharSqlType ) -} \ No newline at end of file +} + +fun ColumnDeclaring.levenshtein(target: ColumnDeclaring): FunctionExpression { + return FunctionExpression( + functionName = "levenshtein", + arguments = listOf(this.asExpression(), target.asExpression()), + sqlType = IntSqlType + ) +} + +fun ColumnDeclaring.levenshtein(target: String): FunctionExpression = + levenshtein(wrapArgument(target)) \ No newline at end of file