寻求帮助,帮助如何建立Ktor,与Redis合作,处理对JSON类型的文本搜索。
图书馆和样本代码都是为 Java撰写的。
寻找具体帮助,对JSON物体进行文字搜索。
e:redis.ftSearch(query,searchOptions)
看看Redis docs, 即它全部用于贾瓦,与科特林无关。 我找不到任何专设的红树图书馆。
寻求帮助,帮助如何建立Ktor,与Redis合作,处理对JSON类型的文本搜索。
图书馆和样本代码都是为 Java撰写的。
寻找具体帮助,对JSON物体进行文字搜索。
e:redis.ftSearch(query,searchOptions)
看看Redis docs, 即它全部用于贾瓦,与科特林无关。 我找不到任何专设的红树图书馆。
最后,我向两家图书馆表示要为此使用。
/building.gradle.kts
dependencies {
// Lettuce for Redis
implementation("io.lettuce:lettuce-core:6.2.6.RELEASE")
implementation("com.redis:lettucemod:3.6.3") // Extension library
}
页: 1 RedisSearchCommands.kt
// Define the Redis Search Commands
// Yes, its odd that we have to define the commands this way, but it s how it works.
interface RedisSearchCommands : Commands {
@Command("FT.CREATE")
@CommandNaming(strategy = CommandNaming.Strategy.DOT)
fun ftCreate(index: String, vararg args: String): String
@Command("FT.ADD")
@CommandNaming(strategy = CommandNaming.Strategy.DOT)
fun ftAdd(index: String, docId: String, score: Double, vararg fields: Any): String
@Command("FT.CONFIG SET")
@CommandNaming(strategy = CommandNaming.Strategy.DOT)
fun ftConfigSet(key: String, value: String): String
@Command("FT.CONFIG GET")
@CommandNaming(strategy = CommandNaming.Strategy.DOT)
fun ftConfigGet(key: String): String
@Command("FT.DROPINDEX")
@CommandNaming(strategy = CommandNaming.Strategy.DOT)
fun ftDropindex(index: String): String
}
/ Application.kt
@OptIn(InternalSerializationApi::class, ExperimentalLettuceCoroutinesApi::class)
fun Application.module() {
val redisClient: RedisModulesClient = RedisModulesClient.create("redis://localhost:6379")
val redisConnection: StatefulRedisModulesConnection<String, String> = redisClient.connect()
val redisSyncCommands: RedisModulesCommands<String, String> = redisConnection.sync()
val redisCoroutineCommand = redisConnection.coroutines()
val redisReactiveCommand = redisConnection.reactive(
// setup the search commands not included in libraries
val redisSearchCommands = RedisCommandFactory(redisConnection).getCommands(RedisSearchCommands::class.java)
redisSearchCommands.ftConfigSet("MINPREFIX", "1") // allow one character prefix for FT.SEARCH
// TEST REDIS JSON SEARCH
try {
// check if index exists
val result = redisSyncCommand.ftInfo("users_index")
} catch (e: Exception) {
// setup json text search index
val result = redisSyncCommand.ftCreate(
"users_index",
CreateOptions.builder<String, String>()
.prefix("user:")
.on(CreateOptions.DataType.JSON)
.build(),
Field.tag("$.id") // note: TAGs do not separate words/special characters
.`as`("id")
.build(),
Field.tag("$.email")
.`as`("email")
.build(),
Field.text("$.name")
.`as`("name")
.sortable()
.withSuffixTrie() // for improved search (go -> going, goes, gone)
.build()
)
if (result != "OK") {
ktorLogger.error("Error creating index: $result")
}
}
val redisInfo = redisSyncCommand.info("users_index")
println("redisInfo: $redisInfo")
val resultRedisAdd1 = redisSyncCommand.jsonSet(
"user:1",
"$", // path
"""
{
"id": "00000000-0000-0000-0000-000000000001",
"email": "chris@alpha.com",
"name": "Chris"
}
""".trimIndent()
)
println("resultRedisAdd1: $resultRedisAdd1")
val resultRedisAdd2 = redisSyncCommand.jsonSet(
"user:2",
"$",
"""
{
"id": "00000000-0000-0000-0000-000000000002",
"email": "billy@beta.com",
"name": "Billy"
}
""".trimIndent()
)
println("resultRedisAdd2: $resultRedisAdd2")
val escapedSearchId = "0000-000000000001".escapeRedisSearchSpecialCharacters()
val resultIdSearch = redisSyncCommand.ftSearch(
"users_index",
"@id:{*$escapedSearchId*}" // search for 0000-000000000001 in id
)
println("resultIdSearch: $resultIdSearch")
val resultTagSearch = redisSyncCommand.ftSearch(
"users_index",
"@email:{*ch*}" // search for ch in email, note use curly-braces for TAG type
)
println("resultTagSearch: $resultTagSearch")
val resultTextSearch = redisSyncCommand.ftSearch(
"users_index",
"@name:*bi*" // search for bi in name, note NO curly-braces for TEXT type
)
println("resultTextSearch: $resultTextSearch")
@Serializable
data class UserSearchResult(
val email: String,
val name: String,
)
val resultArray = resultTagSearch.map { resultMap ->
val resultValue = resultMap.get("$") as String
jsonConfig.decodeFromString<UserSearchResult>(resultValue)
}
println("resultArray: $resultArray")
routing {
route("/redis") {
get("/keys") {
val keys = redisCoroutineCommand.keys("*")
val output: ArrayList<String> = arrayListOf()
keys.collect { key ->
output += key
}
call.respondJson(mapOf("keys" to output.toString()))
}
get("/jsonGet") {
val key = call.request.queryParameters["key"]
key ?: run {
call.respondJson(mapOf("error" to "Missing key"), HttpStatusCode.BadRequest)
return@get
}
val paths = call.request.queryParameters["paths"] ?: "$"
val value = redisReactiveCommand.jsonGet(key, paths) ?: run {
call.respondJson(mapOf("error" to "Key not found"), HttpStatusCode.NotFound)
return@get
}
call.respondJson(mapOf("key" to key, "value" to (value.block()?.toString() ?: "null")))
}
get("/jsonSet") {
val key = call.request.queryParameters["key"] ?: run {
call.respondJson(mapOf("error" to "Missing key"), HttpStatusCode.BadRequest)
return@get
}
val paths = call.request.queryParameters["paths"] ?: "$"
val value = call.request.queryParameters["value"] ?: run {
call.respondJson(mapOf("error" to "Missing value"), HttpStatusCode.BadRequest)
return@get
}
val result = redisReactiveCommand.jsonSet( key, paths, value) ?: run {
call.respondJson(mapOf("error" to "Failed to set key"), HttpStatusCode.InternalServerError)
return@get
}
call.respondJson(mapOf("success" to Json.encodeToString(result.block())))
}
}
}
}
fun String.escapeRedisSearchSpecialCharacters(): String {
val escapeChars =
"""
,.<>{}[]" :;!@#$%^&*()-+=~"
""".trimIndent()
var result = this
escapeChars.forEach {
result = result.replace(it.toString(), "\$it")
}
return result
}
• 启用Ktor服务器,并可以使用任何浏览器(或邮递员)进行以下指挥:
页: 1
- Get json object
http://localhost:8081/redis/jsonGet?key={keyId}&paths={paths}
- Example:
http://localhost:8081/redis/jsonGet?key=user:1&paths=$
http://localhost:8081/redis/jsonGet?key=user:1&paths=.name
- Set json object
http://localhost:8081/redis/jsonSet?key={keyId}&paths={paths}&value={value}
- Example
http://localhost:8081/redis/jsonGet?key=user:1&paths=$.name&value="Jimmy"
页: 1
http://localhost:8081/redis/keys
i have a search form which is shown with Thickbox inside an iframe. the problem is.. that after i click "search" the result page is shown inside the same iframe! and i want it to be shown in the main ...
If I submit a sitemap.xml which does not contain all of the pages of my site, will this affect my search ranking? For example: If my sitemap only contained pages that had been created in the last ...
I have an application that uses lucene for searching. The search space are in the thousands. Searching against these thousands, I get only a few results, around 20 (which is ok and expected). However,...
i made a program that search logical drives to find a specific file .if user type file name an click search button , searching begins , but i don t know how to stop searching in the middle of process....
I have inherited a piece of work where the entry screen shows a summary of 20 calculated variables. E.g. Var A (250), Var B (79). Clicking on any of these links takes the user to a view with a ...
I have an Access app where I use search functionality. I have a TextBox and a Search Button on the form, and it does a wildcard search of whatever the user enters in the TextBox, and displays the ...
I need to implement a custom search in a grid and I would like to find some user interface guidelines that explain the standard way to implement it. I mean this kind of search that is initiated by ...
I am looking for an opinion on the whether to use Google custom search, Yahoo search builder or build my own for web projects (no more than 100 pages of content). If I should build my own - do you ...