-->
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.  [ 7 posts ] 
Author Message
 Post subject: Hibernate search and range query on BigDecimal
PostPosted: Mon Jul 16, 2012 10:02 am 
Newbie

Joined: Mon Dec 19, 2005 9:18 pm
Posts: 17
Location: Brussels, Belgium
I'm having a hard time designing a query to search all instances of Item class with price between 100 and 200.

Here is my Item class:

Code:
@Entity
public class Item {
    @Id @DocumentId
    Long id

    @Field(index = Index.UN_TOKENIZED, store = Store.YES)
    @NumericField
    @FieldBridge(impl = BigDecimalNumericFieldBridge.class)
    BigDecimal price = BigDecimal.ZERO
}


BigDecimalNumericFieldBridge being the class described here: https://hibernate.onjira.com/secure/att ... ed_doc.txt

Luke shows me that I have several documents whose price is between 100 and 200.

Here is my query:
Code:
FullTextSession fullTextSession = Search.getFullTextSession(session);
final QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Item).get();

Query rootQuery = queryBuilder.bool()
    .must(queryBuilder.range().onField('price').above(100).createQuery())
    .must(queryBuilder.range().onField('price').below(200).createQuery())
    .createQuery();

FullTextQuery ftq = fullTextSession.createFullTextQuery(rootQuery, Item);
List<Item> instanceList = ftq.list();


But the list is always empty, no matter the bounds.
Any idea of what I'm doing wrong?

By the way, I'm using Hibernate Search 3.4.1 with Hibernate 3.6.10.

_________________
Sébastien Arbogast


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Mon Jul 16, 2012 10:18 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

do you take the store factor into consideration? See also:


--Hardy


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Mon Jul 16, 2012 10:22 am 
Newbie

Joined: Mon Dec 19, 2005 9:18 pm
Posts: 17
Location: Brussels, Belgium
hardy.ferentschik wrote:


What do you mean by that? As you can see, the value of price is stored in my index, which allows me to see that I have matching documents with Luke. For example, an Item with price 152.40 is stored in the index as a document whose price is 15240.

_________________
Sébastien Arbogast


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Mon Jul 16, 2012 1:05 pm 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Quote:
What do you mean by that? As you can see, the value of price is stored in my index, which allows me to see that I have matching documents with Luke.


All I see it maybe store = Store.YES. what and what not you see in Luke I don't know. I also cannot see whether your BigDecimal is 1.00 and you are searching for "100" because that's your multiplication factor in the bridge, or whether your value is literally 100.

Quote:
For example, an Item with price 152.40 is stored in the index as a document whose price is 15240.


Good a concrete example. What do you search for in the DSL? 152.40 or 15240. I think you should try the former, because the query DSL will try to apply configured bridges for you. If you would write native Lucene queries you would have to use multiplied values (all provided you are using the exact implementation of the bridge you are referring to).

--Hardy


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Tue Jul 17, 2012 3:16 am 
Newbie

Joined: Mon Dec 19, 2005 9:18 pm
Posts: 17
Location: Brussels, Belgium
In order to find my item whose price is 152.40, my query is the one I mentioned earlier:

Code:
Query rootQuery = queryBuilder.bool()
    .must(queryBuilder.range().onField('price').above(100).createQuery())
    .must(queryBuilder.range().onField('price').below(200).createQuery())
    .createQuery();


I just tried by multiplying by 100 and the result is the same: no result

Code:
Query rootQuery = queryBuilder.bool()
    .must(queryBuilder.range().onField('price').above(10000).createQuery())
    .must(queryBuilder.range().onField('price').below(20000).createQuery())
    .createQuery();

_________________
Sébastien Arbogast


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Tue Jul 17, 2012 7:00 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

try:

Code:
Query rootQuery = queryBuilder.bool()
    .must(queryBuilder.range().onField('price').above(10000l).createQuery())
    .must(queryBuilder.range().onField('price').below(20000l).createQuery())
    .createQuery();


Numeric range queries in Lucene are type specific (int, double, long, etc). You are storing the values as long, but when you create the query you are using effectively ints which will give you a mismatch.

Here is a working unit test I used to test this:

Code:
public class NumericBigDecimalBridgeTest extends SearchTestCase {

   public void testNumericFieldWithBigDecimals() throws Exception {
      Session session = openSession();
      Transaction tx = session.beginTransaction();

      // create entities
      Item item = new Item();
      item.setPrice( new BigDecimal( 154.34 ) );
      session.save( item );

      tx.commit();

      tx = session.beginTransaction();
      FullTextSession fullTextSession = Search.getFullTextSession( session );

      QueryBuilder queryBuilder = fullTextSession.getSearchFactory()
            .buildQueryBuilder()
            .forEntity( Item.class )
            .get();

      Query rootQuery = queryBuilder.bool()
            .must( queryBuilder.range().onField( "price" ).above( 10000l ).createQuery() )
            .must( queryBuilder.range().onField( "price" ).below( 20000l ).createQuery() )
            .createQuery();


      List<Item> resultList = ( List<Item> ) fullTextSession.createFullTextQuery( rootQuery, Item.class ).list();
      assertNotNull( resultList );
      assertTrue( resultList.size() == 1 );

      tx.commit();

      session.close();
   }

   @Override
   protected Class<?>[] getAnnotatedClasses() {
      return new Class<?>[] { Item.class };
   }

   @Entity
   @Indexed
   public static class Item {
      @Id
      @GeneratedValue
      private int id;

      @Field
      @NumericField
      @FieldBridge(impl = BigDecimalNumericFieldBridge.class)
      private BigDecimal price;

      public BigDecimal getPrice() {
         return price;
      }

      public void setPrice(BigDecimal price) {
         this.price = price;
      }

      public int getId() {
         return id;
      }
   }

   public static class BigDecimalNumericFieldBridge extends NumericFieldBridge {
      private static final BigDecimal storeFactor = BigDecimal.valueOf( 100 );

      @Override
      public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
         if ( value != null ) {
            BigDecimal decimalValue = ( BigDecimal ) value;
            long indexedValue = decimalValue.multiply( storeFactor ).longValue();
            luceneOptions.addNumericFieldToDocument( name, indexedValue, document );
         }
      }

      @Override
      public Object get(String name, Document document) {
         String fromLucene = document.get( name );
         BigDecimal storedBigDecimal = new BigDecimal( fromLucene );
         return storedBigDecimal.divide( storeFactor );
      }
   }
}



--Hardy


Top
 Profile  
 
 Post subject: Re: Hibernate search and range query on BigDecimal
PostPosted: Tue Jul 17, 2012 7:30 am 
Newbie

Joined: Mon Dec 19, 2005 9:18 pm
Posts: 17
Location: Brussels, Belgium
Thanks a lot. Problem solved. You are my hero!

_________________
Sébastien Arbogast


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.