What is the role of #Indexable in elasticsearch-osem? - java

I'm looking into integrating elasticsearch into my spring-jpa driven application.
For this purpose the elasticsearch-osem project seems an amazing fit.
What I can't understand is what is the role of the #Indexable(indexName = "someIndex") annotation which is shown in the example from the introduction to the project.
What confuses me is the fact that in the same example it says:
Then you can write objects to the ElasticSearch client:
node.client().prepareIndex("twitter", "tweet","1").setSource(context.write(tweet)).execute().actionGet();
Where "twitter" is the index-name.
I think my question is why should one also define an #Indexable on a field and why should they define an index-name?
Thanks

With #Indexable you say which fields should be included in the index. The indexName is the name of the field in the index. This is not the name of the index, which you set with your other call.
From Javadoc:
/**
* The name of the field that will be stored in the index. Defaults to the property/field name.
*/
String indexName() default "";

After looking through the source code I was able to see that the #Indexable is used to either supply aliases to the fields of indexed properties in indexed entities or to allow indexing of properties in un-indexed entities.
You can see this in the getIndexableProperties method in the AttributeSourceImpl type where it says in a comment:
Searchable class properties are implicitly Indexable

Related

How to make field in document unique?

I am using spring data mongo. There is a field in document apart from primary key which needs to be unique but as per my requirement I can't use #Indexed(unique=true). Is there any annotation like #Column(unique=true) in spring data mongo to make the field as a unique?
Following method can also be used to define indexes programmatically. The advantage of this method is that it provides programmatic control for defining indexes.
this.mongoTemplate.indexOps(<Document>.class).ensureIndex(new Index("<fieldName>", Direction.ASC).unique());
What you need is a sparse index in this case.
Try #Indexed(unique=true, sparse=true). Do read the documentation for this type of index here

Hibernate Search with Elasticsearch creating fields with .keyword suffix

I just implemented the integration of Hibernate Search with Elasticsearch using hibernate search 5.8 and ES 5.5.
I have several fields created specifically for sorting, and they are all called [field]Sort.
When I was testing it locally, the first time I let Hibernate create the indexes, it created the String sort fields like this:
nameSort -> text
nameSort.keyword -> keyword
I realized that I should use the suffixed field for sorting.
But then, when I destroyed my Elasticsearch cluster, to start over, it didn't create the suffixed fields, it just created the sort fields as keyword directly.
I recreated the cluster 5 or more times again and it never created the suffixed fields again.
When I finally sent my changes to our staging environment, it created the suffixed fields again, causing my queries to fail, because they are trying to sort by a text field, instead of a keyword field.
Now, I'm really not sure of why it sometimes creates the suffix and sometimes doesn't.
Is there any rule?
Is there a way to avoid it creating 2 fields and making it always create only one keyword field with exactly the name I gave it?
Here's an example of a sort field:
#Field(name = "nameSort", analyze = Analyze.NO, store = Store.YES, index = Index.NO)
#SortableField(forField = "nameSort")
public String getNameSort() {
return name != null ? name.toLowerCase(Locale.ENGLISH) : null;
}
Thanks in advance for any help.
Hibernate Search does no such thing as creating a separate keyword field for text fields. It creates either a text field or a keyword field, depending on whether the field should be analyzed. In your case, the field is not analyzed, so it should create a keyword field.
Now, Hibernate Search is not alone here, and this behavior could stem from the Elasticsearch cluster itself. Did you check whether you have particular index templates on your Elasticsearch cluster? It could lead to Elasticsearch creating a keyword field whenever Hibernate Search creates a text property.
On a side note, you may be interested by the fact Hibernate Search 5.8 allows defining normalizers (same thing as Elasticsearch normalizers), which would allow you to annotate the getName() getter directly and avoid doing the lowercase conversion yourself. See this blog post for more information.

Multiple default values for collections with Jersey

I'm using Jersey and want a set that, when not added as a query param, defaults to a set containing more than one object.
I basically want this:
#DefaultValue("test1", "test2")
#QueryParam("test")
private Set<MyEnum> test;
to return a set containing the enums "test1" and "test2".
I'm having no problem getting a single default value to work but I would like multiple. The docs are a bit cryptical, is it possible?
According to this source from stackoverflow and the official documentation you can only do this by manually checking if the object is null then set the default value

Validating Java objects field-by-field

I'm doing analyses on Java validation.
I need to build a module that validates an object [graph] field-by-field, using annotation and supporting custom domain-driven annotations. The most important aspect is that an invalid object must not be rejected (e.g. by underlying persistence layer) but instead marked as invalid.
For example, pick a class with a number of attributes. If any is invalid (e.g. missing or bad valued) I want to know which one is and mark it in another place as invalid. It is important that I get the name of all the fields that didn't pass validation, whether it's a primitive field or a child entity with a validation problem.
I have taken a look at javax.validation but I couldn't figure out the role of ConstraintViolation: it is returned by the validator when a validation error is found, but AFAIK doesn't show the field name to collect.
The question is: do you have any example of using any implementation of javax.validation that display the list of the field names that are found to be invalid for each validated bean?
Also, can I introduce custom attributes instead of adding a ValidatedBy attribute for each recurring attribute to be validated with custom logic?
If you want the name of the element that caused the ConstraintViolation you must use
Path path = ConstraintViolation.getPropertyPath();
// a path is an iterable of Path.Node objects
// the last node element in the path is the element that caused the violation
// You can get it's name via
Path.Node node = ...;
node.getName();
Take a look at the JSR-303 spec chapter 4.2 for details on the Path.

specifying custom properties to a displaytag table decorator

I have a decorator specified on a displaytag table that I need to pass parameters to. The decorator adds an id attribute to the row. Currently the values I require are hardcoded.
The parameters I need are:
The name of the property to use as id value
An id prefix (usually the property used is a number and IE doesn't like ids starting with numbers)
Looking through the javadocs for displaytag, it looks like I can set a property (<displaytag:setProperty>), but there doesn't seem to be a way for me to return a general property.
Decorators have access to the PageContext. You can pass parameters as its attributes (for example, using <c:set .../>).
Maybe you can provide a little bit more of info? Show us your decorator implementation pls.
If I got you right: You need the id of the iterated property? If you implement the
DisplaytagColumnDecorator
Interface, you can access the iterated property by
decorate(java.lang.Object columnValue, javax.servlet.jsp.PageContext pageContext, MediaTypeEnum media)
where columValue is your property object for each row.

Categories

Resources