Spring Data Solr Facet Range example? - spring

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

Related

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));

Spring Data Elasticsearch Problem with IP_Range Data type

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",
...
},
...
}
}

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.

Sorting a custom JPA query with pageable

So, I've already done this using the standard Spring Data JPA interface which extends PagingAndSortingRepository in order to achieve pagination and sorting for a REST API. The thing is, now I want to achieve the very same thing but now using just vanilla JPA and so far so good I managed to get my API to paginate but the sorting doesn't work at all. Every time I try to set the parameter (from a pageable object using pageable.getSort()) it ends with a query error (either if I just send a string as parameter like "name" or just send the sort object, it shows errors).
Here's some code:
My repo implementation:
#Override
public List<Project> findByAll(Pageable pageable) {
Query query = em.createQuery("SELECT project FROM Project project ORDER BY :sort");
query.setParameter("sort", pageable.getSort());
query.setMaxResults(pageable.getPageSize());
query.setFirstResult(pageable.getPageSize() * pageable.getPageNumber());
return query.getResultList();
}
My service:
#Override
public Page<Project> findAll(Pageable pageable) {
objects = Lists.newArrayList(repository.findByAll(pageable));
PageImpl<Project> pages= new PageImpl<Project>(objects, pageable, repository.count());
return pages;
}
To be clear, I'm filling the Pageable object via URI and from the console I can say it's actually getting the data, so I assume the problem is with the repo.
Edit: This is the error I get when I replace the setParameter("sort", ...) for a hardcoded string aka query.setParameter("sort", "name"):
java.lang.NumberFormatException: For input string: "name"
And I think this method should stand for strings as well. If I use query.setParameter("sort", pageable.getSort()), the error is the same.
The order by cannot be set as a query parameter. Also, the Pageable.getSort().toString() likely won't return a string suitable for use in an order by clause as it will result in a String that represents the Order as property: ORDER, note the colon.
Here are some modifications that will work, assuming Java 8...
String order = StringUtils.collectionToCommaDelimitedString(
StreamSupport.stream(sort.spliterator(), false)
.map(o -> o.getProperty() + " " + o.getDirection())
.collect(Collectors.toList()));
Query query = em.createQuery(
String.format("SELECT project FROM Project project ORDER BY %s", order));

Elasticsearch document id type integer vs string : Is there any performace difference?

I am using elasticsearch 2.3.1. Currently all the document ids are integer. But I have a situation where the document ids can be numeric valued or sometimes alpha-numeric string. So I need to make the field type 'string'.
So, I need to know if there is any performance difference based on the type of Id. Please help....
Elasticsearch will store the id as a String even if your mapping says otherwise:
"mappings": {
"properties": {
"id": {
"type": "integer"
},
That is my mapping, but when I do a sort on _id I get documents ordered as:
10489, 10499, 105, 10514...
i.e. in String order.
Latest version of ES (7.14) mandates the document's _id to be a String. You can see it in the documentation for org.elasticsearch.action.index.IndexRequest. IndexRequest mandates the _id to be a String field alone. No other types are supported. Example usage of IndexRequest can be found here: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-index.html
In case, the above link stops working later, here is the snippet from the link:
IndexRequest request = new IndexRequest("posts");
request.id("1"); //This is the only method available to set the document's _id.
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);

Resources