-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: DSL QueryBuilder onField doesn't work polymorphically?
PostPosted: Mon Feb 14, 2011 4:59 am 
Beginner
Beginner

Joined: Wed Sep 30, 2009 5:29 am
Posts: 29
Hibernate 3.6.0, HSearch 3.3.0. Quick newbie question regarding the QueryBuilder.

I have an ItemEntity and some derived entities, in my demo app I have a WineEntity with specific indexed fields concerning bottles of wine. My question is, can I use a QueryBuilder built for the parent class ItemEntity to build queries for attributes of WineEntity, or will I have to use the Lucene API directly to add such a field query?

I have found that the QueryBuilder's keyword() builder can only specify onField for attributes of ItemEntity. You cannot specify fields for subclasses such as WineEntity.

Code:
@Entity @Indexed
public class ItemEntity {
.. core item attributes ..
}

@Entity @Indexed
public class WineEntity extends ItemEntity {
  @Column @Field
  private String appellation;
}


Now I prepare a QueryBuilder for ItemEntity, and later try to tell it to query on an attribute that actually belongs to a child class of ItemEntity:

Code:
QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder()
      .forEntity(ItemEntity.class).get();
.. cut ..
for (each query like "appellation='whatever'") {
   b.must(qb.keyword().onField(attr.getKey()).matching(attr.getValue()).createQuery());
}


throws:

Code:
Caused by: org.hibernate.search.SearchException: Unable to find field appellation in ltd.yavin.liveauction.db.ItemEntity
        at org.hibernate.search.engine.DocumentBuilderIndexedEntity.objectToString(DocumentBuilderIndexedEntity.java:607)
        at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.buildSearchTerm(ConnectedMultiFieldsTermQueryBuilder.java:133)
        at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:92)
        at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:73)
        at myApp.buildItemSearchQuery(DBSearchHelper.java:167)


The documentation under "5.1. Building queries" is good, and in 5.1.2 pushes us to use the HSearch DSL API for preference, but doesn't specify the details of using it with polymorphic entity classes.

Should I not use the DSL API, and build a Lucene query term directly?

Thank you
Nick


Top
 Profile  
 
 Post subject: Re: DSL QueryBuilder onField doesn't work polymorphically?
PostPosted: Mon Feb 14, 2011 3:21 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
You can use the QueryBuilder targeting the subclass, and then still target the Query to the superclass to include types which don't have an appellation field.

I don't think this usage was expected, but please help us figuring out how it would be more easy to use. Would you expect the QueryBuilder to know all fields of subtypes? What would you expect from:
Code:
searchFactory.buildQueryBuilder().forEntity( Object.class )
?

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
 Post subject: Re: DSL QueryBuilder onField doesn't work polymorphically?
PostPosted: Tue Feb 15, 2011 3:20 am 
Beginner
Beginner

Joined: Wed Sep 30, 2009 5:29 am
Posts: 29
s.grinovero wrote:
You can use the QueryBuilder targeting the subclass, and then still target the Query to the superclass to include types which don't have an appellation field.

In my case, I don't want to build the QueryBuilder targeting the subclass, because my app works on the basis of a core ItemEntity class, with any number of possible child Entity classes for each customised environment I deploy to. The frontend passes to the backend all fields to search on, and my generic search utils build the Queries required to search on those fields. The 'appellation' field name is passed into my generic search code from a customised frontend. The core code only knows about the parent ItemEntity class, and not about the child WineEntity which has the appellation field. (the WineEntity instances themselves are created and indexed via another set of custom code).

So, I wanted to always build a QueryBuilder for my parent class, but be able to specify onField() clauses for fields that are found on child classes.

I know this goes against standard OO practise.. but in the world of Lucene indexes, the index will contain fields for both parent and child class, i.e.:

_hibernate_class: my.app.WineEntity
coreItemField: 1000
appellation: foobar

(in case you're wondering, yes, this is a completely different problem to the @IndexEmbedded JIRA I raised recently)

I see via Luke that the _hibernate_class indicates what Entity class should be used to instantiate this object.. to be honest, I don't yet understand how to think about the mapping of Java Entity classes to Lucene index Documents.

s.grinovero wrote:
I don't think this usage was expected, but please help us figuring out how it would be more easy to use. Would you expect the QueryBuilder to know all fields of subtypes? What would you expect from:
Code:
searchFactory.buildQueryBuilder().forEntity( Object.class )
?


Good question. QueryBuilder should only know to act on @Indexed classes, and hopefully the job of inspecting them and all subtypes is fairly straightforward, if not already done at SessionFactory instantiation time.

I did hope that QueryBuilder would know all fields of subtypes. But, perhaps QueryBuilder is doing The Right Thing, and I should approach the problem differently. In OO terms, it doesn't make sense to have a reference of the type of the parent class and expect it to know about members in derived classes; the inheritance system works the other way, a reference to a child class would naturally know about members of parent classes/interfaces. I don't know if it is a good idea to build this kind of introspection into HSearch.

For now, I work around by catching a SearchException when trying to specify onField for every field specified, and for those that fail, I build a plain Lucene TermQuery, knowing that Lucene's index will contain the field, even if HSearch cannot figure out what I'm talking about. Perhaps I will run into trouble with the analyzers and tokenizers used on the field.. I haven't read over the docs enough times for that complex info to sink in yet :)

Nick


Top
 Profile  
 
 Post subject: Re: DSL QueryBuilder onField doesn't work polymorphically?
PostPosted: Tue Feb 15, 2011 4:51 am 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Quote:
Good question. QueryBuilder should only know to act on @Indexed classes, and hopefully the job of inspecting them and all subtypes is fairly straightforward, if not already done at SessionFactory instantiation time.
I did hope that QueryBuilder would know all fields of subtypes.

Referring to Object.class is an exaggeration of course, but I wanted to point out that they are potentially many different types; also as we have to choose the analyzer for each field, this means we would need to mandate unique names across all indexed entities.

I think you should use the DSL to create a Query targeting the parent entity, and then use a BooleanQuery to combine it with additional keyword queries. Remember, if you use the TermQuery directly you'll have to pre-Analyze the input yourself before building the Query, or rather use a queryparser targeting the additional nonstandard fields; hopefully your frontend is able to tell you the Analyzer types too, or you use a single conventional Analyzer for all.

Another option, your frontend tells you the target type it's searching for.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.