Re: [hibernate-dev] Questions on HS + ES

2017-05-10 Thread Yoann Rodiere
Hi,

> * Can we have multiple indexes for the same entity, with different
> fields, geared towards different use cases?

No, it's not currently possible. Each entity is mapped to a single index.
But you can map each property of your entity to multiple index
"properties", so you can actually handle multiple use cases in a single
index.
We could probably think about adding the feature you describe, and it may
even not be very difficult (expect a few things that we'll have to do
anyway). But I fail to see the added value compared to having all those
fields in a single index. Performance-wise, I doubt it would change
anything, and on the user side the mapping would likely become harder to
understand (especially uses of @IndexedEmbedded).

> * How could we deal with authorization for seeing specific ES query
> results? I reckon that's something to mostly (solely?) handle on the
> ES side?

Hibernate Search itself does not provide any authorization features.
You can add security either:

   - on the ES side (with Shield) to define what the *application* is
   allowed to access (only the application scope makes sense here, since we
   use a single username for every request). This would involve updating index
   settings after they've been created or creating index templates before the
   indexes are created.
   - on the client side to define what a specific *user* is allowed to
   access, for example by annotating your services with Spring Security, which
   allows both pre-execution checks ("is this query parameter allowed") and
   post-execution checks ("is every result in the result set visible for the
   given user").

> * Are dynamic analyzers supported for the ES backend?

Nope, as mentioned in the docs [1]. They simply cannot be supported as is,
since with Elasticsearch, analyzers cannot be chosen when indexing, only
when creating the mapping.

> * And a wish for the docs: make clear which kind of changes towards
> mapped entities require a re-index run?

Any change that would result in already indexed entities to be indexed
differently: adding a new field based on pre-existing data, renaming a
field, changing its encoding (text to numeric for instance), changing how
it's analyzed (tokenizer, filter), making it stored while it previously
wasn't...
It's easier to state which changes do *not* require a re-index run,
actually:

   - new indexes/fields based on currently empty data, e.g. a new property
   in an entity that is currently empty for every entity, or a new index
   mapping for an entity that hasn't any database row yet.
   - feature reduction, e.g. making a previously stored field not stored,
   or removing a field. The data will stay in the index, we just won't use it
   nor update it anymore.

I created a ticket about this: HSEARCH-2715 [2].


Of course the limitations I just mentioned above are not carved in stone.
Hibernate Search evolves continuously, and if user feel like a specific
feature is missing, they can request it through JIRA.

[1]
https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#elasticsearch-limitations
[2] https://hibernate.atlassian.net/browse/HSEARCH-2715


Yoann Rodière
Hibernate NoORM Team
yo...@hibernate.org

On 9 May 2017 at 16:09, Gunnar Morling  wrote:

> Hi,
>
> I recently got some good questions on Hibernate Search + Elastisearch:
>
> * Can we have multiple indexes for the same entity, with different
> fields, geared towards different use cases?
> * How could we deal with authorization for seeing specific ES query
> results? I reckon that's something to mostly (solely?) handle on the
> ES side?
> * Are dynamic analyzers supported for the ES backend?
> * And a wish for the docs: make clear which kind of changes towards
> mapped entities require a re-index run?
>
> Any replies would be welcome.
>
> Thanks,
>
> --Gunnar
> ___
> hibernate-dev mailing list
> hibernate-dev@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
___
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Re: [hibernate-dev] Preventing duplicate ForeignKey generation

2017-05-10 Thread Milo van der Zee
Finally done... See https://github.com/hibernate/hibernate-orm/pull/1906

MAG,
Milo


On 01/09/2017 01:02 PM, Vlad Mihalcea wrote:
> Thanks,
>
> Please send a Pull Request with a replicating test case.
>
> Vlad
>
> On Wed, Dec 28, 2016 at 12:05 AM, Milo van der Zee  > wrote:
>
> Hello all,
>
> During development of applications I'm used to set the schema creation
> to 'update' (hbm2ddl.auto = update). This makes life a bit easier.
> Issue with the newer version of Hibernate is that the name of the
> generated keys changed and so all keys are regenerated. For the large
> databases I use this takes hours and has to be done every time a fresh
> copy from production is taken to the development environment.
>
> I do use meaningful names for the indexes where possible. But when
> using
> abstract classes used by the entities that is not possible because the
> same fields from the abstract are used by many entity classes and so
> would end up having the same index names.
>
> I checked the code that decides if the index needs to be created and
> found that it only checks the name of the index. Not what the index
> actually does. This is why I changed that piece of code to be a bit
> smarter. It is desinged for simple constraints from one column to
> another column. Not for multi to multi column indexes and constraints.
>
> I created a Jira issue for it but nobody notices it and there are no
> comments or anything else. So now I try it here :)
> Jira HHH-10934 (https://hibernate.atlassian.net/browse/HHH-10934
> )
>
> Code fragment I put in SchemaMigratorImpl.java:
>
> private  ForeignKeyInformation findMatchingForeignKey(ForeignKey
> foreignKey, TableInformation tableInformation) {
> if  (foreignKey.getName() ==null) {
> return  null;
> }
>
> /*
>  * Find existing keys based on referencing column and
> referencedTable
>  */
> String  referencingColumn = foreignKey.getColumn(0).getName();
> String  referencedTableName =
> foreignKey.getReferencedTable().getName();
> Iterable existingForeignKeys =
> tableInformation.getForeignKeys();
> for  (ForeignKeyInformation existingKey :
> existingForeignKeys) {
> Iterable
> columnReferenceMappings = existingKey.getColumnReferenceMappings();
> for  (ColumnReferenceMapping mapping :
> columnReferenceMappings) {
> String  existingReferencingColumn =
> mapping.getReferencingColumnMetadata().getColumnIdentifier().getText();
> String  existingReferencedTableName =
> 
> mapping.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName();
> if 
> (referencingColumn.equals(existingReferencingColumn) &&
> referencedTableName.equals(existingReferencedTableName)) {
> return  existingKey;
> }
> }
> }
>
> // If not yet found check based on key name  return 
> 
> tableInformation.getForeignKey(Identifier.toIdentifier(foreignKey.getName()));
> }
>
> Or if you prever the Java 8 way:
>
> private  ForeignKeyInformation findMatchingForeignKey(ForeignKey
> foreignKey, TableInformation tableInformation) {
> log.debug("findMatchingForeignKey");
> if  (foreignKey.getName() ==null)return  null;
>
> /*
>  * Find existing keys based on referencing column and
> referencedTable
>  */
> String  referencingColumn = foreignKey.getColumn(0).getName();
> String  referencedTableName =
> foreignKey.getReferencedTable().getName();
> Predicate mappingPredicate = m ->
> 
> referencingColumn.equals(m.getReferencingColumnMetadata().getColumnIdentifier().getText())
> &&
> 
> referencedTableName.equals(m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName());
> for  (ForeignKeyInformation existingKey :
> tableInformation.getForeignKeys()) {
> boolean  found =
> 
> StreamSupport.stream(existingKey.getColumnReferenceMappings().spliterator(),false).anyMatch(mappingPredicate);
> if  (found)return  existingKey;
> }
>
> // If not yet found check based on key name  return 
> 
> tableInformation.getForeignKey(Identifier.toIdentifier(foreignKey.getName()));
> }
>
> The calling method does not use the returned value. It only checks if
> the returned value is null or not. So this could also be cleaned by
> changi

Re: [hibernate-dev] Preventing duplicate ForeignKey generation

2017-05-10 Thread Vlad Mihalcea
Thanks,

Vlad

On Wed, May 10, 2017 at 7:07 PM, Milo van der Zee 
wrote:

> Finally done... See https://github.com/hibernate/hibernate-orm/pull/1906
>
> MAG,
> Milo
>
>
>
> On 01/09/2017 01:02 PM, Vlad Mihalcea wrote:
>
> Thanks,
>
> Please send a Pull Request with a replicating test case.
>
> Vlad
>
> On Wed, Dec 28, 2016 at 12:05 AM, Milo van der Zee 
> wrote:
>
>> Hello all,
>>
>> During development of applications I'm used to set the schema creation
>> to 'update' (hbm2ddl.auto = update). This makes life a bit easier.
>> Issue with the newer version of Hibernate is that the name of the
>> generated keys changed and so all keys are regenerated. For the large
>> databases I use this takes hours and has to be done every time a fresh
>> copy from production is taken to the development environment.
>>
>> I do use meaningful names for the indexes where possible. But when using
>> abstract classes used by the entities that is not possible because the
>> same fields from the abstract are used by many entity classes and so
>> would end up having the same index names.
>>
>> I checked the code that decides if the index needs to be created and
>> found that it only checks the name of the index. Not what the index
>> actually does. This is why I changed that piece of code to be a bit
>> smarter. It is desinged for simple constraints from one column to
>> another column. Not for multi to multi column indexes and constraints.
>>
>> I created a Jira issue for it but nobody notices it and there are no
>> comments or anything else. So now I try it here :)
>> Jira HHH-10934 (https://hibernate.atlassian.net/browse/HHH-10934)
>>
>> Code fragment I put in SchemaMigratorImpl.java:
>>
>> private  ForeignKeyInformation findMatchingForeignKey(ForeignKey
>> foreignKey, TableInformation tableInformation) {
>> if  (foreignKey.getName() ==null) {
>> return  null;
>> }
>>
>> /*
>>  * Find existing keys based on referencing column and
>> referencedTable
>>  */
>> String  referencingColumn = foreignKey.getColumn(0).getName();
>> String  referencedTableName = foreignKey.getReferencedTable(
>> ).getName();
>> Iterable existingForeignKeys =
>> tableInformation.getForeignKeys();
>> for  (ForeignKeyInformation existingKey : existingForeignKeys) {
>> Iterable columnReferenceMappings
>> = existingKey.getColumnReferenceMappings();
>> for  (ColumnReferenceMapping mapping :
>> columnReferenceMappings) {
>> String  existingReferencingColumn =
>> mapping.getReferencingColumnMetadata().getColumnIdentifier().getText();
>> String  existingReferencedTableName =
>> mapping.getReferencedColumnMetadata().getContainingTableInfo
>> rmation().getName().getTableName().getCanonicalName();
>> if  
>> (referencingColumn.equals(existingReferencingColumn)
>> && referencedTableName.equals(existingReferencedTableName)) {
>> return  existingKey;
>> }
>> }
>> }
>>
>> // If not yet found check based on key name return
>> tableInformation.getForeignKey(Identifier.toIdentifier(
>> foreignKey.getName()));
>> }
>>
>> Or if you prever the Java 8 way:
>>
>> private  ForeignKeyInformation findMatchingForeignKey(ForeignKey
>> foreignKey, TableInformation tableInformation) {
>> log.debug("findMatchingForeignKey");
>> if  (foreignKey.getName() ==null)return  null;
>>
>> /*
>>  * Find existing keys based on referencing column and
>> referencedTable
>>  */
>> String  referencingColumn = foreignKey.getColumn(0).getName();
>> String  referencedTableName = foreignKey.getReferencedTable(
>> ).getName();
>> Predicate mappingPredicate = m ->
>> referencingColumn.equals(m.getReferencingColumnMetadata().
>> getColumnIdentifier().getText())
>> && referencedTableName.equals(m.g
>> etReferencedColumnMetadata().getContainingTableInformation()
>> .getName().getTableName().getCanonicalName());
>> for  (ForeignKeyInformation existingKey :
>> tableInformation.getForeignKeys()) {
>> boolean  found = StreamSupport.stream(existingK
>> ey.getColumnReferenceMappings().spliterator(),false).
>> anyMatch(mappingPredicate);
>> if  (found)return  existingKey;
>> }
>>
>> // If not yet found check based on key name return
>> tableInformation.getForeignKey(Identifier.toIdentifier(
>> foreignKey.getName()));
>> }
>>
>> The calling method does not use the returned value. It only checks if
>> the returned value is null or not. So this could also be cleaned by
>> changing the method to return a boolean and then remove the for loop in
>> java-8 and use flatmap. But first let us agree on the validity of the
>> idea to change this piece of code.
>>
>> I hope anybody would like to have a loo