lucene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Greg Fodor (JIRA)" <>
Subject [jira] Issue Comment Edited: (SOLR-2202) Money FieldType
Date Wed, 03 Nov 2010 16:50:24 GMT


Greg Fodor edited comment on SOLR-2202 at 11/3/10 12:50 PM:

Please ignore, there are problems in the current patch, will update later today.

      was (Author: gfodor):
    This update to the patch includes a number of performance enhancements and is the version
of the patch we will be likely to push to production.

First, this patch introduces the defaultCurrency parameter, which defaults to USD. The default
currency allows you to omit the currency code in the field value (ie, "5000" instead of "5000,USD".)
However, it plays a more pivotal role in improving performance.

The previous patches provided a native approach to constructing the trie bounding range by
taking the max and min currency exchange rates for the target currency. This proved to be
minimally useful since the relative value of currency units vary wildly and hence the bounding
range often spanned the full document set.

The solution I took in this patch is to compute the bounding range by taking into account
the "currency drift." Before getting to that, though, the indexing process was updated to
include a new dynamic field that indexes the value of the field in the *default currency*,
exchanged at the current rate at indexing time. (Additionally, a stored field is optionally
created if the money field is marked as stored.)

Now, the appreciative and depreciative drifts of a currency C are defined to be the difference
between the current exchange rate and the peak and trough exchange rates seen for the life
of the index from C to the default currency. By taking the largest drifts (both appreciating
and depreciating) across all currencies, a optimal and correct bounding range to use for a
trie query against the default currency can be computed.

The historical max and min exchange rates relative to the default currency are now tracked
by solr in a properties file. The properties file is named after the currency config file.
For example, if the config file is "currency.xml", the properties file is "".
This file is designed to work correctly with replication, and is updated by Solr whenever
the currency config file is loaded.

For example, if the default currency is USD, and over the life of the index the EUR exchange
rate to USD is seen to be 1.1, 1.4, and 1.3, the max and min exchange rates are clearly 1.1
and 1.4. If the current exchange rate at query time is 1.3, the "depreciative drift" for EUR
is 1.3 - 1.1 = 0.2, and the "appreciative drift" is 1.4 - 1.3 = 0.1. If the query being made
is for ($100, $200), the lower bound is adjusted based upon the depreciative drift to $100
- (0.2 * $100) = $80, and the upper bound is adjusted based upon the appreciative drift to
$200 + (0.1 * $200) = $220. 

This is an accurate bounding range for the indexed default currency value, since those are
the max and min possible values that were indexed regardless of the time the indexing occured.
So, the trie query is formed to query against the new dynamic field that indexes the original
value as the default currency, over the bounds ($80, $220). The trie query is appended to
a boolean clause that further constrains the results by doing the actual conversion to determine
if the current exchange rate will still yield it as matching the user's range query.

Beyond this, I added some additional intra-query caching and changed the query construction
from the FilteredQuery approach (which seemed to be inefficient in leveraging the trie query)
to the BooleanQuery. You'll note that I rely upon the second clause in the BooleanQuery being
scored first, which eliminates the expensive exchange rate conversions from happening for
documents that fall outside the trie range. 

I ran into a limitation of the current resource loader API, however, in that it does not allow
access to creating or writing new resources, which is needed to maintain the drift properties
file. For now, I only support SolrResourceLoader which writes to the local filesystem by extracting
the config directory. However, the new ZkResourceLoader is not supported, for example. A non-fatal
warning is emitted to the log when this occurs. The side effect of this is that currency exchange
rate drift will not be tracked, resulting in incorrect range and point queries if the currency.xml
file is updated. It would be nice if it were possible to ask the ResourceLoader for an OutputStream
to a new resource for this purpose.

Some limitations:
- The default currency cannot be changed after the initial index, otherwise the index effectively
is corrupt since the value for the trie bound is indexed in the default currency.
- Loss or corruption of the drift file will cause erroneous range and point queries (documents
will be omitted from the results, though no incorrect documents will appear.)
- As mentioned above, the only ResourceLoader supported are SolrResourceLoaders that respond
to getConfigDir(). Please let me know if there is a safer, more canonical way to store and
load Solr-maintained metadata that lives with the index.

Also note that this has been tested with replication. The only thing necessary for replication
to work is that the currency.xml and file be included as part
of the replication. A limitation here is that if no documents are updated but the currency
exchange rates change, the file will not be replicated due to Solr's policy of not replicating
files without index changes. It would be useful to allow this behavior to be overridden. In
our case this isn't a problem since our index churn is high enough that replication events
happen regularly.

In the end these changes result in accurate currency range queries that perform nearly as
fast as their non-currency counterparts. 

> Money FieldType
> ---------------
>                 Key: SOLR-2202
>                 URL:
>             Project: Solr
>          Issue Type: New Feature
>          Components: Schema and Analysis
>    Affects Versions: 1.5
>            Reporter: Greg Fodor
>         Attachments: SOLR-2022-solr-3.patch, SOLR-2202-lucene-1.patch, SOLR-2202-solr-1.patch,
SOLR-2202-solr-2.patch, SOLR-2202-solr-4.patch, SOLR-2202-solr-5.patch, SOLR-2202-solr-6.patch
> Attached please find patches to add support for monetary values to Solr/Lucene with query-time
currency conversion. The following features are supported:
> - Point queries (ex: "price:4.00USD")
> - Range quries (ex: "price:[$5.00 TO $10.00]")
> - Sorting.
> - Currency parsing by either currency code or symbol.
> - Symmetric & Asymmetric exchange rates. (Asymmetric exchange rates are useful if
there are fees associated with exchanging the currency.)
> At indexing time, money fields can be indexed in a native currency. For example, if a
product on an e-commerce site is listed in Euros, indexing the price field as "10.00EUR" will
index it appropriately. By altering the currency.xml file, the sorting and querying against
Solr can take into account fluctuations in currency exchange rates without having to re-index
the documents.
> The new "money" field type is a polyfield which indexes two fields, one which contains
the amount of the value and another which contains the currency code or symbol. The currency
metadata (names, symbols, codes, and exchange rates) are expected to be in an xml file which
is pointed to by the field type declaration in the schema.xml.
> The current patch is factored such that Money utility functions and configuration metadata
lie in Lucene (see MoneyUtil and CurrencyConfig), while the MoneyType and MoneyValueSource
lie in Solr. This was meant to mirror the work being done on the spacial field types.
> This patch has not yet been deployed to production but will be getting used to power
the international search capabilities of the search engine at Etsy.

This message is automatically generated by JIRA.
You can reply to this email to add a comment to the issue online.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message