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
Related
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.
Idea:
Convert the POJO into flat map using
ObjectToMapTransformer
and form a solrinputdocument from the map and store it in Solr.
While retrieving get the document from the Solr and convert the Document into map and to POJO using MapToObjectTransformer
Problem:
While saving the SolrinputDocument to Solr the flatten key like A.B[0].c of the POJO is getting converted to A.B_0_.c in Solr.
This alternate form of storage in Solr makes it difficult to deserialize the solrDocument to POJO.
How to solve this problem? Or what is the alternate way of storing queryable Document in Solr which can be deserialized and serialized easily.
You usually wrap the fields in your POJO with the appropriate Solr fields that you're indexing that field into. See Mapping a POJO for Solr.
If you really want to serialize the complete object into Solr, serialize it into a single field, and if possible, use a string field (as that will store your object directly). If you want to actually search string values inside the object as well, you can use a text field - but since everything is imported into a single field, that'll have a few limitations (like if you want to score different fields or search for values in a single property from the objects).
So: Use the #Field annotation from SolrJ.beans to do specific POJO handling, or mangle it into a single field and search for strings in that field.
How can I define some value should be unique in Neo4j?
for example think I want to store users data in node,so username should be unique.Is there any way to do it like what we do in sql ( define username as unique properties )?
For this you will need to use a node index and the uniqueness features available within the API to ensure that only one node is filed under each key-value pair. If you're working with Neo4j embedded then have a look at:
http://api.neo4j.org/1.8/org/neo4j/graphdb/index/Index.html#putIfAbsent(T,
java.lang.String, java.lang.Object)
http://api.neo4j.org/1.8/org/neo4j/graphdb/index/UniqueFactory.html
For the REST interface, you may have uniqueness support already in the library that you are using or, if you are not using a library, this page should help:
http://docs.neo4j.org/chunked/milestone/rest-api-unique-indexes.html
As node structures are not enforced in the same way that record structures are enforced in most RDBMSs, there is no direct equivalent to the UNIQUE KEY feature that you mention. Index uniqueness should however give you the same end result.
Hope this helps
Nige
I have some long name classes which I store in the database using Hibernate.
I've noticed that hibernate creates the dtype column (for inheritance support) as character varying(31).
Since the class name is longer than 31 characters the insert fails.
What is the best way to resolve it?
Since I have lots of classes I prefer some global setting over adding annotation to each class.
Alternative to JB Nizets answer is by specifying
#DiscriminatorColumn(length=100)
would provide a column that is long enough.
Use #DiscriminatorValue("some_short_name") to all your subclasses. I don't think there is any other solution.
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