The APIs for managing documents (index
, delete
, and update
) are the most important after the search ones. In this recipe, we will see how to use them.
You need an up-and-running Elasticsearch installation, as we described in the Downloading and installing Elasticsearch recipe in Chapter 2, Downloading and Setup.
A Maven tool, or an IDE that supports Scala programming, such as Eclipse (ScalaIDE) or IntelliJ IDEA, with the Scala plugin should be installed.
The code of this recipe can be found in the chapter_15/elastic4s_sample
file and the referred class is DocumentExample
.
For managing documents, we will perform the following steps:
import com.sksamuel.elastic4s.ElasticDsl._
object DocumentExample extends App with ElasticSearchClientTrait{ val indexName="myindex" val typeName="mytype" ensureIndexMapping(indexName, typeName)
indexInto
call:client.execute { indexInto(indexName / typeName) id "0" fields ( "name" -> "brown", "tag" -> List("nice", "simple") ) }.await
get
call:val bwn=client.execute { get("0") from indexName / typeName }.await println(bwn.sourceAsString)
update
call using a script in Painless:client.execute { update("0").in(indexName / typeName).script("ctx._source.name = 'red'") }.await
val red=client.execute { get("0") from indexName / typeName }.await println(red.sourceAsString)
no modules loaded loaded plugin [org.elasticsearch.index.reindex.ReindexPlugin] loaded plugin [org.elasticsearch.percolator.PercolatorPlugin] loaded plugin [org.elasticsearch.script.mustache.MustachePlugin] loaded plugin [org.elasticsearch.transport.Netty3Plugin] loaded plugin [org.elasticsearch.transport.Netty4Plugin] {"name":"brown","tag":["nice","simple"]} {"name":"red","tag":["nice","simple"]}
The document version, following an update action and if the document is re-indexed with new changes, is always incremented by 1
.
Before executing a document action, a client and the index must be available and document mapping should be created (the mapping is optional, because it can be inferred from the indexed document).
To index a document, elastic4s allows us to provide the document content in several ways, such as via:
fields
:(String, Any)
as in the preceding exampleMap[String, Any]
Iterable[(String, Any)]
doc/source
:Indexable[T]
Obviously, it's possible to add all the parameters that we saw in the Indexing a document recipe in Chapter 4, Basic Operations, such as parent, routing, and so on.
The return value, IndexReponse
, is the same retuned object from the Java call.
To retrieve a document, we need to know the index
/type
/id
; the method is get
. It requires the id
and the index
, type
provided in the from
method. A lot of other methods are available to control the routing (such as souring, parent) or fields as we have seen in the Getting a document recipe in Chapter 4, Basic Operations. In the preceding example, the call is:
val bwn=client.execute { get("0") from indexName / typeName }.await
The return type, GetResponse
, contains all the requests (if the document exists) and the document information (source
, version
, index
, type
, and id
).
To update a document, it's required to know the index
/type
/id
and provide a script or a document to be used for the update. The client method is update
. In the preceding example, we have used a script:
client.execute { update("0").in(indexName / typeName).script("ctx._source.name = 'red'") }.await
The script code must be a string. If the script language is not defined, the default Painless is used.
The returned response contains information about the execution and the new version value to manage concurrency.
To delete a document (without the need to execute a query), we must know the index
/type
/id
and we can use the client method, delete
, to create a delete
request. In the preceding code, we have used:
client.execute { delete("0") from indexName / typeName }.await
The delete
request allows all the parameters we saw in the Deleting a document recipe in Chapter 4, Basic Operations, to control routing and versions, to be passed to it.
Scala programmers love typeclass, automatic marshalling/unmarshalling from case classes, and a strong type management of the data. For this, elastics4 provides additional support for the common JSON serialization library, such as:
"com.sksamuel.elastic4s" %% "elastic4s-circe" % elastic4sV
"com.sksamuel.elastic4s" %% "elastic4s-jackson" % elastic4sV
"com.sksamuel.elastic4s" %% "elastic4s-json4s" % elastic4sV
For example, if you want to use Circe, perform the following steps:
circe
implicits:import com.sksamuel.elastic4s.circe._ import io.circe.generic.auto._ import com.sksamuel.elastic4s.Indexable
case
class that needs to be deserialized:case class Place(id: Int, name: String)
implicitly[Indexable[Cafe]]
val cafe=Cafe("nespresso", Place(20,"Milan")) client.execute { indexInto(indexName / typeName).id(cafe.name).source(cafe) }.await
In the recipes, we have used all CRUD operations on a document. For more details about these actions, refers to:
3.129.208.25