Spring Data Elasticsearch Problem with IP_Range Data type - spring-boot

I use Spring boot 2.0.1.RELEASE/ Spring Data Elasticsearch 3.0.6.
I annotate my domain class with #Document annotation and i have a field as below:
#Field(store = true, type = FieldType.?)
private String ipRange;
as you see, I need to set the field type to IP_Range (exists in elastic search engine data types)
but not exists in FieldType enum.
I want to create this document index by ElasticsearchTemplate.createIndex(doc) method. but none of any FieldType enum support ip_range data type.

Spring Data Elasticsearch currently (3.2.0.M2) does not support this. I saw that you already opened an issue, thanks for that. The answer here is just for the completeness and for other users having the same problem

Thanks #P.J.Meisch for your reply, I used #Mapping annotation to specify my mapping directly via json format. Already Spring data supports creating index based on this config. but i am also waiting for Range Data Structure Support to refactor my code.
My Document:
#Document(createIndex = true, indexName = "mydomain", type = "doc-rule"
, refreshInterval = BaseDocument.REFRESH_INTERVAL, replicas = BaseDocument.REPLICA_COUNT, shards = BaseDocument.SHARD_COUNT)
#Mapping(mappingPath = "/elasticsearch/mappings/mydomain-mapping.json")
public class MyDomainDoc {
#Field(store = true, type = FieldType.text)
private List<String> ipRange;
... other fields
}
And My mydomain-mapping.json file:
{
"properties": {
...,
"ipRange": {
"type": "ip_range",
...
},
...
}
}

Related

Spring Data JPA projection issue with field starting with IS in kotlin

I'm using interface based projection to get certain fields from db. one of my field name start with is. I'm able to get the field from database via native query, however, the response returned by spring boot controller does not contain is in field name. How should I resolve it?
interface UserProjection {
val userId: Long
val isPrivate: Boolean
val likesCount: Int
}
Query
SELECT u.user_id as userId, u.is_private as private, u.likes_count as likesCount FROM users u WHERE u.user_id=?;
However, response returned by spring boot is
{
"userId": 12345,
"private": false,
"likesCount": 1
}
The solution is to use a fun to get the field instead of a val
interface LoginUserProjection {
val id: Long
val passwordHash: String
fun getIsVerifiedAccount(): Boolean
}

Is It possible to dynamically remove indexing on a field on Elasticsearch using spring data?

I need to index all the fields of an Elasticsearch index when building the index, but after some time, if needed change the index value to false and improve the performance by removing indexing from some of the fields.
As I searched, read the docs and tested it with spring data when I set index = false after building the index in #Field there is no change and the field is still searchable.
#Document(indexName = "book")
#Setting(refreshInterval = "30s", shards = 3)
class Book(
#Id
#Field(type = FieldType.Keyword)
var id: String? = null,
#Field(type = FieldType.Keyword )
var title: String? = null,
#Field(type = FieldType.Keyword,index = false)
val isbn: String)
I wanted to know if there is another solution to change the indexing of fields dynamically after building the index using spring data?
You'll need to run the modified program with a new index name to create a new index with the adjusted mapping and then manually do a reindexing from the old to the new index: Elasticsearch documentation about reindexing.

How to filter Range criteria using ElasticSearch Repository

I need to fetch Employees who joined between 2021-12-01 to 2021-12-31. I am using ElasticsearchRepository to fetch data from ElasticSearch index.
How can we fetch range criteria using repository.
public interface EmployeeRepository extends ElasticsearchRepository<Employee, String>,EmployeeRepositoryCustom {
List<Employee> findByJoinedDate(String joinedDate);
}
I have tried Between option like below: But it is returning no results
List<Employee> findByJoinedDateBetween(String fromJoinedDate, String toJoinedDate);
My Index configuration
#Document(indexName="employee", createIndex=true,type="_doc", shards = 4)
public class Employee {
#Field(type=FieldType.Text)
private String joinedDate;
Note: You seem to be using an outdated version of Spring Data Elasticsearch. The type parameter of the #Document
annotation was deprecated in 4.0 and removed in 4.1, as Elasticsearch itself does not support typed indices since
version 7.
To your question:
In order to be able to have a range query for dates in Elasticsearch the field in question must be of type date (the
Elasticsearch type). For your entity this would mean (I refer to the attributes from the current version 4.3):
#Nullable
#Field(type = FieldType.Date, pattern = "uuuu-MM-dd", format = {})
private LocalDate joinedDate;
This defines the joinedDate to have a date type and sets the string representation to the given pattern. The
empty format argument makes sure that the additional default values (DateFormat.date_optional_time and DateFormat. epoch_millis) are not set here. This results in the
following mapping in the index:
{
"properties": {
"joinedDate": {
"type": "date",
"format": "uuuu-MM-dd"
}
}
}
If you check the mapping in your index (GET localhost:9200/employee/_mapping) you will see that in your case the
joinedDate is of type text. You will either need to delete the index and have it recreated by your application or
create it with a new name and then, after the application has written the mapping, reindex the data from the old
index into the new one (https://www.elastic.co/guide/en/elasticsearch/reference/7.16/docs-reindex.html).
Once you have the index with the correct mapping in place, you can define the method in your repository like this:
List<Employee> findByJoinedDateBetween(LocalDate fromJoinedDate, LocalDate toJoinedDate);
and call it:
repository.findByJoinedDateBetween(LocalDate.of(2021, 1, 1), LocalDate.of(2021, 12, 31));

Elasticsearch + Spring boot: Query creation from method names for property with #InnerField/#MultiField

I'm trying to build an Elasticsearch query using method name and just curios on what would be the method name if one of the property has multiple fields like following
#MultiField(
mainField = #Field(type = Text, fielddata = true),
otherFields = {
#InnerField(suffix = "keyword", type = Keyword)
}
)
private String resourceType;
I needed "keyword" type (non-analyzed) so I can search it with entire string.
I have tried it as
List<Event> findByResourceType_KeywordIsIn(Collection<String> list);
and getting following error
No property keyword found for type String! Traversed path: Event.resourceType.
Is there anyway I can tell spring-data-elasticsearch that it is for the same property but an InnerField ?
P.S: I can certainly go with either #Query or just build that entire query using NativeSearchQueryBuilder but curios if I can achieve it with just a method name(Less code -> Less unit testing :) )
Thanks
This won't work with the method names of Repository implementations. The logic in Spring Data that does the parsing uses the - possibly nested - properties of the java class whereas you need to have a query searching the resourceType.keyword Elasticsearch field.
So as you already wrote, you'll need a #Query to do this.

Spring Data Solr Facet Range example?

Using Spring data solr 1.4 -- I have FacetQuery defined as such:
#Facet(fields = { "client", "state", “market”, “price" }, limit = 10)
FacetPage<SearchResponse> findTerm(String fieldName, String fieldValue, String filterField, String filterValue, Pageable pageable);
How do I add ranges to the facet price? I don't want all the single values, but 10-20, 20-30, 30-40, etc.
Seems still an open issue. Check:
https://github.com/spring-projects/spring-data-solr/pull/29

Resources