Fix an incompatible type
Table of contents:
What is Elasticsearch?
Elasticsearch is a search and analytics engine. It allows you to store data and search through it with ease, but it is not a database engine per se. It doesn’t guarantee ACID (Atomicity, Consistency, Isolation, Durability) properties. Elasticsearch stores data in an index, which is a special construction that speeds up search queries, but it is vulnerable to corruption. This isn’t a significant issue since all your data should be stored in a proper database engine like MySQL or MongoDB, allowing the index to be rebuilt from it.
Incompatible type
Elasticsearch is RESTful and uses JSON to transfer data. It uses dynamic field mapping to distinguish types of fields. Let’s check an example of JSON, which causes an incompatible type error.
The problem is with field quantity. If Elasticsearch recognizes field as Long and then the same field has fraction then error occures, cause you can’t store Double as Long. This problem also happens when Double is recongized first and then came Long.
There is a quite simple solution for this problem. We need to define types on our own. To demonstrate it, I will assemble small project using Spring Data Elasticsearch.
Project
Foremost, I go to Spring Initializr. I selected: Elasticsearch, DevTools and Lombok. All we really need is Elasticsearch, but DevTools and Lombok does our work easier. To bootstrap our project, we need Elasticsearch engine running. Luckily, it is already build-in feature in our project. First we need to add following annotation to main class.
The last thing we are missing is ElasticsearchTemplate
class. Below is a bean that creates its local instance.
This configuration launches a local Elasticsearch instance every time we run our project, storing indexes in the data
folder in the project root directory. Now, let’s create documents that will be used to demonstrate the previously described problem. First, we’ll create documents that may cause an error.”
We can solve an invalid type recognition by usage of the annotation @Field
. Below I present you fixed documents.
The most important changes are:
the annotation @Field(type = FieldType.Nested)
by property invoicePostions
in class PorperInvoice
annotations @Field(type = FieldType.Double)
in class ProperInvoicePositions
.
These changes are self-explanatory, but don’t forget to used them both. Without FieldType.Nested
your changes in ProperInvoicePostion
class will not matter when you will save ProperInvoice.
@Field(type = FieldType.String)
is not necessary in this example, but I included it to show, how to use this annotation.
You might notice that I used @Field(type = FieldType.Object)
with property saleDate that is type LocalDate. Of course, I could use FieldType.Date, but it doesn’t works out of the box and for an explanation for this problem, I will make an another article.
We defined types by ourself, but Elasticsearch doesn’t know about it. To create indexes with our types we need to do one more action.
Conclusion
Elasticsearch is a great tool to accelerate search queries in your application. It uses the dynamic type recognition, and it might be a problem with numbers. To avoid this problem, we can define types ourself. This can be achieved by a usage of annotation @Field
and creating index before first call to Elasticsearch.
My site is free of ads and trackers. Was this post helpful to you? Why not
Reference:
Disqus is great for comments/feedback but I had no idea it came with these gaudy ads.