开发者

Hibernate Search Fails with Double Type Greater than 5 Digits

开发者 https://www.devze.com 2023-02-11 04:28 出处:网络
I have the following fields on an entity: @Field(index = Index.TOKENIZED, store = Store.YES) @Column(name = \"total_credit_amount\", nullable = false)

I have the following fields on an entity:

@Field(index = Index.TOKENIZED, store = Store.YES)
@Column(name = "total_credit_amount", nullable = false)
@FieldBridge(impl = RoundedDoubleBridge.class)
private Double totalCreditAmount;

@Field(index = Index.TOKENIZED, store = Store.YES)
@Column(name = "total_debit_amount", nullable = false)
@FieldBridge(impl = RoundedDoubleBridge.class)
private Double totalDebitAmount;

The Double to String bridge implementation is the following:

public class RoundedDoubleBridge
    implements StringBridge
{
@Override
    public String objectToString(Object value)
    {
        // Do not index null strings
        if (value == null)
        {
            return null;
        }

        if (value instanceof Double)
        {
            l开发者_如何学Pythonong price = round((Double) value);

            return Long.toString(price);
        }
        else
        {
            throw new IllegalArgumentException(
                RoundedDoubleBridge.class + " used on a non double type: "
                + value.getClass());
        }
    }


    private long round(double price)
    {
        double rounded = Math.floor(price / 3) * 3;

        if (rounded != price)
        {
            rounded += 3; //we round up
        }

        return (long) rounded;
    }
}

So the issue here is that the search I am performing retreives results whenever the values on totalDebitAmount or totalCreditAmount are less than 100000, whenever they are greater or equal to 100000 search fails.. Any help appreciated..

The following is the way I am making the search:

public List<AbstractRecord> doSearch(String stringToFind)
    {
        List<AbstractRecord> result = null;

        // Test Search for specific values of an Abstract Record
        // Aim to return the number of retreived results
        em = emf.createEntityManager();

        FullTextEntityManager fullTextEntityManager =
            org.hibernate.search.jpa.Search.getFullTextEntityManager(em);

        //em.getTransaction().begin();
        String[] fields = // Fields to be reviewed
            new String[]
            {
               ....,
               "totalCreditAmount", "totalDebitAmount",
               ....
            };

        //Create a multi-field Lucene query
        StandardAnalyzer stdAnalyzer = new StandardAnalyzer(Version.LUCENE_30);
        MultiFieldQueryParser parser =
            new MultiFieldQueryParser(Version.LUCENE_30, fields, stdAnalyzer);
        org.apache.lucene.search.Query query = null;

        try
        {
            query = parser.parse(stringToFind);
        }
        catch (ParseException ex)
        {
            Logger.getLogger(SearchFacade.class.getName()).log(Level.SEVERE, null, ex);
        }

        long time1 = System.currentTimeMillis();

        // Wrap Lucene query in a javax.persistence.Query
        javax.persistence.Query persistenceQuery =
            fullTextEntityManager.createFullTextQuery(query);
        // Execute search
        result = (List<AbstractRecord>) persistenceQuery.getResultList();
        em.close();

        return result;
    }


Well I feel kind of dumb. I found my problem.. It is specifically at the rounding function of the implementation of my FieldBridge The relevant snippet of the bridge is the following:

private long round(double price)
    {
        double rounded = Math.floor(price / 3) * 3;

        if (rounded != price)
        {
            rounded += 3; //we round up
        }

        return (long) rounded;
    }

Notice for price = 100000 the variable rounded = 99999 After checking the if condition since its different from price, it will add 3, hence indexing 100002 instead of 100000, therefore If I look up for 100002 I will find the appropriate record..

Lessons learned here:

  • If you are implementing a customized DoubleBridge that pads and/or rounds make sure the rounding function meets all your data value ranges to avoid problems like the one I had..
  • If you need to show in screen rounded up Doubles in plain notation and not scientific, you will need to implement a TwoWayStringBridge that performs the ObjectToString conversion padding and rounding and later on the StringToObject conversion returning a plain notation Double and not on its scientific notation.

Hope this post can help anyone with similar issues. Greets

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号