Skip to content

Commit

Permalink
Implement typed navigation for DynDocSource (ex StdDocSource); gettin…
Browse files Browse the repository at this point in the history
…g started doc
  • Loading branch information
anti-social committed Sep 14, 2021
1 parent 2b166fe commit 953a3cc
Show file tree
Hide file tree
Showing 15 changed files with 639 additions and 65 deletions.
16 changes: 9 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ val allKotlinClassDirs = allprojects
}

allprojects {
if (name != "samples") {
apply {
plugin("org.jetbrains.kotlin.multiplatform")
plugin("jacoco")
}
group = "dev.evo.elasticmagic"
version = "0.0.1"

if (name == "samples") {
return@allprojects
}

group = "dev.evo.elasticmagic"
version = "0.1-SNAPSHOT"
apply {
plugin("org.jetbrains.kotlin.multiplatform")
plugin("jacoco")
}

repositories {
mavenCentral()
Expand Down
63 changes: 62 additions & 1 deletion docs/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,70 @@
# Welcome to Elasticmagic

Elasticmagic implements advanced type awareness DSL for Kotlin to construct Elasticsearch queries.

!!! Warning
The library is in very alpha status. API may change significantly at any time.
Use it on your own risk

## Getting started

First you need to describe a document:
### Setup

Add following dependencies in your `build.gradle.kts` script:

!!! TODO
At the moment artifacts are not yet published on maven central. Stay tuned

```kotlin
repositories {
mavenCentral()
}

val elasticmagicVersion = "0.0.1"
val ktorVersion = "1.5.2"

dependencies {
// Elasticmagic core api
implementation("dev.evo.elasticmagic:elasticmagic:$elasticmagicVersion")
// Json serialization using kotlinx.serialization
implementation("dev.evo.elasticmagic:elasticmagic-serde-serialization-json:$elasticmagicVersion")
// Transport that uses ktor http client
implementation("dev.evo.elasticmagic:elasticmagic-transport-ktor:$elasticmagicVersion")

implementation("io.ktor:ktor-client-cio:$ktorVersion")
}
```

### Using

First you need to describe a document (represents a mapping in terms of Elasticsearch):

```kotlin
--8<-- "../samples/src/main/kotlin/samples/started/UserDoc.kt"
```

Now create `ElasticsearchCluster` object. It is an entry point to execute search queries:

```kotlin
--8<-- "../samples/src/main/kotlin/samples/started/Cluster.kt"
```

Create our index if it does not exist or update the mapping otherwise:

```kotlin
--8<-- "../samples/src/main/kotlin/samples/started/EnsureIndexExists.kt"
```

Describe document sources and index them:

```kotlin
--8<-- "../samples/src/main/kotlin/samples/started/IndexDocs.kt"
```

And finally we can search our data:

```kotlin
--8<-- "../samples/src/main/kotlin/samples/started/Main.kt"
```

You can find fully working sample at https://github.com/anti-social/elasticmagic-kt/tree/master/samples/src/main/kotlin/samples/started
14 changes: 14 additions & 0 deletions samples/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@ plugins {
application
}

repositories {
mavenCentral()
}

dependencies {
implementation(project(":"))
implementation(project(":elasticmagic-serde-serialization-json"))
implementation(project(":elasticmagic-transport-ktor"))

implementation(Libs.ktorClient("cio"))
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
}

application {
Expand Down
15 changes: 15 additions & 0 deletions samples/src/main/kotlin/samples/started/Cluster.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package samples.started

import dev.evo.elasticmagic.ElasticsearchCluster
import dev.evo.elasticmagic.serde.serialization.JsonSerde
import dev.evo.elasticmagic.transport.ElasticsearchKtorTransport

import io.ktor.client.engine.cio.CIO

val esTransport = ElasticsearchKtorTransport(
"http://localhost:9200",
deserializer = JsonSerde.deserializer,
engine = CIO.create {}
)
val cluster = ElasticsearchCluster(esTransport, JsonSerde)
val userIndex = cluster["user"]
17 changes: 17 additions & 0 deletions samples/src/main/kotlin/samples/started/EnsureIndexExists.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package samples.started

import dev.evo.elasticmagic.Params

suspend fun ensureIndexExists() {
if (!cluster.indexExists(userIndex.name)) {
cluster.createIndex(
userIndex.name,
mapping = UserDoc,
settings = Params(
"index.number_of_replicas" to 0,
),
)
} else {
cluster.updateMapping(userIndex.name, mapping = UserDoc)
}
}
50 changes: 50 additions & 0 deletions samples/src/main/kotlin/samples/started/IndexDocs.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package samples.started

import dev.evo.elasticmagic.DynDocSource
import dev.evo.elasticmagic.IndexAction
import dev.evo.elasticmagic.IdentActionMeta
import dev.evo.elasticmagic.list
import dev.evo.elasticmagic.Refresh

suspend fun indexDocs() {
val docs = listOf(
DynDocSource {
// Note that you can't write like following (it just won't compile):
// it[UserDoc.id] = "0"
// it[UserDoc.name] = 123
// it[UserDoc.groups.list()] = "root"
it[UserDoc.id] = 0
it[UserDoc.name] = "root"
it[UserDoc.groups.list()] = listOf("root", "wheel")
it[UserDoc.about] = "Super user"
},
DynDocSource {
it[UserDoc.id] = 1
it[UserDoc.name] = "daemon"
it[UserDoc.groups.list()] = listOf("daemon")
it[UserDoc.about] = "Daemon user"
},
DynDocSource {
it[UserDoc.id] = 65535
it[UserDoc.name] = "nobody"
it[UserDoc.groups.list()] = listOf("nobody")
it[UserDoc.about] = "Just nobody"
},
DynDocSource {
it[UserDoc.id] = 65534
it[UserDoc.name] = "noone"
it[UserDoc.groups.list()] = listOf("nobody")
it[UserDoc.about] = "Another nobody"
},
)
// Create index actions, make bulk request and refresh the index
userIndex.bulk(
docs.map { doc ->
IndexAction(
meta = IdentActionMeta(id = doc[UserDoc.id].toString()),
source = doc,
)
},
refresh = Refresh.TRUE,
)
}
43 changes: 42 additions & 1 deletion samples/src/main/kotlin/samples/started/Main.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
package samples.started

fun main() {}
import dev.evo.elasticmagic.DynDocSource
import dev.evo.elasticmagic.SearchQuery
import dev.evo.elasticmagic.SearchQueryResult
import dev.evo.elasticmagic.TermsAgg
import dev.evo.elasticmagic.TermsAggResult

fun printUsers(result: SearchQueryResult<DynDocSource>) {
println("Found: ${result.totalHits} users")
for (hit in result.hits) {
val user = hit.source!!
println(" ${user[UserDoc.id]}: ${user[UserDoc.name]}")
}
println()
}

fun printGroupsAgg(aggResult: TermsAggResult) {
println("Groups aggregation")
for (bucket in aggResult.buckets) {
println(" ${bucket.key}: ${bucket.docCount}")
}
}

suspend fun main() {
ensureIndexExists()
indexDocs()

// Find all users
val sq = SearchQuery()
printUsers(sq.execute(userIndex))

// Find nobody users
sq.query(UserDoc.about.match("nobody"))
printUsers(sq.execute(userIndex))

// Build an aggregation that counts users inside a group
printGroupsAgg(
SearchQuery()
.aggs("groups" to TermsAgg(UserDoc.groups))
.execute(userIndex)
.agg<TermsAggResult>("groups")
)
}
1 change: 1 addition & 0 deletions samples/src/main/kotlin/samples/started/UserDoc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import dev.evo.elasticmagic.Document
object UserDoc : Document() {
val id by int()
val name by keyword()
val groups by keyword()
val about by text()
}
Loading

0 comments on commit 953a3cc

Please sign in to comment.