按照計劃,這篇開始嘗試用elastic4s來作一系列索引管理和搜索操做示範。前面提過,elastic4s的主要功能之一是經過組合Dsl語句造成json請求。那麼咱們先試試組合一些Dsl語句,再想辦法產生出json請求文本,而後在kibana控制檯中驗證它的正確性。json
首先看看elastic4s提供的一個show函數:app
def show(implicit handler: Handler[T, _]): String = Show[ElasticRequest].show(handler.build(t))
又見到了這個Handler[T, _],做爲show的一個隱式參數。前面說過這個Handler[T, _]是個表明構建T類型json請求的typeclass。具體構建函數就是上面的這個build(t)函數。咱們先看看CreateIndexRequest類型的show函數示範:函數
val jsCreate = createIndex("company") .shards(1).replicas(1).show println(jsCreate)
產生了json以下:ui
PUT:/company? StringEntity({"settings":{"index":{"number_of_shards":1,"number_of_replicas":1}}},Some(application/json))
在kibana裏是以下表達的:spa
PUT /company { "settings":{ "index":{ "number_of_shards":1, "number_of_replicas":1 } } }
多是歷史緣由吧,elastic4s與ES7.6還有不少不兼容的地方,或者說是elastic4s還有許多沒來得及更新的地方。具體有問題的語句或參數均可以經過把json body放在kibana裏進行驗證,若是elastic4s還有地方沒有完成覆蓋ES7.6功能的話,咱們能夠把一個正確的ES7.6 json腳本直接經過source傳人到操做類型中去:scala
val js =
""" |{ | "settings":{ | "index":{ | "number_of_shards":1, | "number_of_replicas":1
| } | } |} |""".stripMargin
val createFromJs = (createIndex("company").source(js)).show println(createFromJs)
下面的例子是一套完整的索引建立過程:先刪除同名稱索引、建立索引、構建mapping:code
import com.sksamuel.elastic4s.ElasticClient import com.sksamuel.elastic4s.akka._ import akka.actor._ import com.sksamuel.elastic4s.requests.mappings.{KeywordField, MappingDefinition, NestedField, SearchAsYouTypeField} import scala.concurrent.ExecutionContext.Implicits.global
object Lesson03 extends App { import com.sksamuel.elastic4s.ElasticDsl._ //akka客戶端
private implicit lazy val system: ActorSystem = ActorSystem() val akkaClient = AkkaHttpClient(AkkaHttpClientSettings(List("localhost:9200"))) val client = ElasticClient(akkaClient) //刪除索引
val idxDelete = client.execute(deleteIndex("company")).await
//構建索引
val idxCreate = client.execute(createIndex("company") .shards(1).replicas(1)).await
//建立表結構
if(idxCreate.isSuccess) { val compMapping = client.execute( putMapping("company").fields( KeywordField("code"), SearchAsYouTypeField("name") .fielddata(true) .fields(KeywordField("keyword")), textField("biztype"), NestedField("addr").fields( textField("district"), textField("address"), KeywordField("zipcode") ), dateField("regdate") .ignoreMalformed(true) .format("strict_date_optional_time||epoch_millis"), textField("contact") )).await
if(compMapping.isSuccess) println(s"mapping successfully created.") else println(s"mapping creation error: ${compMapping.error.reason}") } else { println(s"index creation error: ${idxCreate.error.reason}") } system.terminate() client.close() }
以上代碼有幾個地方值得提一下:orm
一、這上面使用了一個基於akka-stream的客戶端。優勢是響應式標準兼容,用隊列queue來緩衝密集請求blog
二、在刪除索引前爲甚麼不先檢查一下同名索引是否存在?elastic4s ExistApi仍是ES7之前版本,不能用索引
三、client.execute(...)返回Future, 爲何不用for-yield?試過了,一是deleteIndex,createIndex返回結果與實際刪除、構建操做可能有些延遲,createIndex會返回索引已經存在錯誤, mapping會出現索引不存在錯誤。