mirror of https://github.com/apache/lucene.git
SOLR-10503,SOLR-10502: Deprecate CurrencyField in favor of new CurrencyFieldType, which works with point fields and provides control over dynamic fields used for the raw amount and currency code sub-fields.
This commit is contained in:
parent
af1ee47f2b
commit
a6f4f2dd9c
|
@ -343,6 +343,8 @@ Upgrade Notes
|
|||
|
||||
* SOLR-10379: ManagedSynonymFilterFactory has been deprecated in favor of ManagedSynonymGraphFilterFactory.
|
||||
|
||||
* SOLR-10503: CurrencyField has been deprecated in favor of new CurrencyFieldType.
|
||||
|
||||
New Features
|
||||
----------------------
|
||||
|
||||
|
@ -490,6 +492,10 @@ Other Changes
|
|||
rendered visibly in the PDF. Also add .adoc file checks to the top-level validate target, including
|
||||
for the invisible substitutions PDF problem. (Steve Rowe)
|
||||
|
||||
* SOLR-10503,SOLR-10502: Deprecate CurrencyField in favor of new CurrencyFieldType, which works
|
||||
with point fields and provides control over dynamic fields used for the raw amount and currency
|
||||
code sub-fields. (hossman, Steve Rowe)
|
||||
|
||||
================== 6.6.1 ==================
|
||||
|
||||
Bug Fixes
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,829 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.analysis.util.ResourceLoader;
|
||||
import org.apache.lucene.analysis.util.ResourceLoaderAware;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.FieldValueQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.solr.uninverting.UninvertingReader.Type;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.response.TextResponseWriter;
|
||||
import org.apache.solr.search.Filter;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.QueryWrapperFilter;
|
||||
import org.apache.solr.search.SolrConstantScoreQuery;
|
||||
import org.apache.solr.search.function.ValueSourceRangeFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Field type for support of monetary values.
|
||||
* <p>
|
||||
* See <a href="http://wiki.apache.org/solr/CurrencyField">http://wiki.apache.org/solr/CurrencyField</a>
|
||||
*/
|
||||
public class CurrencyFieldType extends FieldType implements SchemaAware, ResourceLoaderAware {
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
protected static final String PARAM_DEFAULT_CURRENCY = "defaultCurrency";
|
||||
protected static final String DEFAULT_DEFAULT_CURRENCY = "USD";
|
||||
protected static final String PARAM_RATE_PROVIDER_CLASS = "providerClass";
|
||||
protected static final String DEFAULT_RATE_PROVIDER_CLASS = "solr.FileExchangeRateProvider";
|
||||
protected static final String PARAM_FIELD_SUFFIX_AMOUNT_RAW = "amountLongSuffix";
|
||||
protected static final String PARAM_FIELD_SUFFIX_CURRENCY = "codeStrSuffix";
|
||||
|
||||
protected IndexSchema schema;
|
||||
protected FieldType fieldTypeCurrency;
|
||||
protected FieldType fieldTypeAmountRaw;
|
||||
protected String fieldSuffixAmountRaw;
|
||||
protected String fieldSuffixCurrency;
|
||||
|
||||
private String exchangeRateProviderClass;
|
||||
private String defaultCurrency;
|
||||
private ExchangeRateProvider provider;
|
||||
|
||||
/**
|
||||
* A wrapper around <code>Currency.getInstance</code> that returns null
|
||||
* instead of throwing <code>IllegalArgumentException</code>
|
||||
* if the specified Currency does not exist in this JVM.
|
||||
*
|
||||
* @see Currency#getInstance(String)
|
||||
*/
|
||||
public static Currency getCurrency(final String code) {
|
||||
try {
|
||||
return Currency.getInstance(code);
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* :NOOP: */
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(IndexSchema schema, Map<String, String> args) {
|
||||
super.init(schema, args);
|
||||
if (this.isMultiValued()) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||
getClass().getSimpleName() + " types can not be multiValued: " + this.typeName);
|
||||
}
|
||||
this.schema = schema;
|
||||
|
||||
this.defaultCurrency = args.get(PARAM_DEFAULT_CURRENCY);
|
||||
if (this.defaultCurrency == null) {
|
||||
this.defaultCurrency = DEFAULT_DEFAULT_CURRENCY;
|
||||
} else {
|
||||
args.remove(PARAM_DEFAULT_CURRENCY);
|
||||
}
|
||||
if (null == getCurrency(this.defaultCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"Default currency code is not supported by this JVM: " + this.defaultCurrency);
|
||||
}
|
||||
|
||||
this.exchangeRateProviderClass = args.get(PARAM_RATE_PROVIDER_CLASS);
|
||||
if (this.exchangeRateProviderClass == null) {
|
||||
this.exchangeRateProviderClass = DEFAULT_RATE_PROVIDER_CLASS;
|
||||
} else {
|
||||
args.remove(PARAM_RATE_PROVIDER_CLASS);
|
||||
}
|
||||
try {
|
||||
Class<? extends ExchangeRateProvider> c
|
||||
= schema.getResourceLoader().findClass(exchangeRateProviderClass, ExchangeRateProvider.class);
|
||||
provider = c.newInstance();
|
||||
provider.init(args);
|
||||
} catch (Exception e) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR,
|
||||
"Error instantiating exchange rate provider " + exchangeRateProviderClass + ": " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (fieldTypeAmountRaw == null) { // Don't initialize if subclass already has done so
|
||||
fieldSuffixAmountRaw = args.get(PARAM_FIELD_SUFFIX_AMOUNT_RAW);
|
||||
if (fieldSuffixAmountRaw == null) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Missing required param " + PARAM_FIELD_SUFFIX_AMOUNT_RAW);
|
||||
} else {
|
||||
args.remove(PARAM_FIELD_SUFFIX_AMOUNT_RAW);
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldTypeCurrency == null) { // Don't initialize if subclass already has done so
|
||||
fieldSuffixCurrency = args.get(PARAM_FIELD_SUFFIX_CURRENCY);
|
||||
if (fieldSuffixCurrency == null) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Missing required param " + PARAM_FIELD_SUFFIX_CURRENCY);
|
||||
} else {
|
||||
args.remove(PARAM_FIELD_SUFFIX_CURRENCY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPolyField() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkSchemaField(final SchemaField field) throws SolrException {
|
||||
super.checkSchemaField(field);
|
||||
if (field.multiValued()) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||
getClass().getSimpleName() + " fields can not be multiValued: " + field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IndexableField> createFields(SchemaField field, Object externalVal) {
|
||||
CurrencyValue value = CurrencyValue.parse(externalVal.toString(), defaultCurrency);
|
||||
|
||||
List<IndexableField> f = new ArrayList<>();
|
||||
SchemaField amountField = getAmountField(field);
|
||||
f.add(amountField.createField(String.valueOf(value.getAmount())));
|
||||
SchemaField currencyField = getCurrencyField(field);
|
||||
f.add(currencyField.createField(value.getCurrencyCode()));
|
||||
|
||||
if (field.stored()) {
|
||||
String storedValue = externalVal.toString().trim();
|
||||
if (storedValue.indexOf(",") < 0) {
|
||||
storedValue += "," + defaultCurrency;
|
||||
}
|
||||
f.add(createField(field.getName(), storedValue, StoredField.TYPE));
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private SchemaField getAmountField(SchemaField field) {
|
||||
return schema.getField(field.getName() + POLY_FIELD_SEPARATOR + fieldSuffixAmountRaw);
|
||||
}
|
||||
|
||||
private SchemaField getCurrencyField(SchemaField field) {
|
||||
return schema.getField(field.getName() + POLY_FIELD_SEPARATOR + fieldSuffixCurrency);
|
||||
}
|
||||
|
||||
/**
|
||||
* When index schema is informed, get field types for the configured dynamic sub-fields
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param schema {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void inform(IndexSchema schema) {
|
||||
this.schema = schema;
|
||||
if (null == fieldTypeAmountRaw) {
|
||||
assert null != fieldSuffixAmountRaw : "How did we get here?";
|
||||
SchemaField field = schema.getFieldOrNull(POLY_FIELD_SEPARATOR + fieldSuffixAmountRaw);
|
||||
if (field == null) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Field type \"" + this.getTypeName()
|
||||
+ "\": Undefined dynamic field for " + PARAM_FIELD_SUFFIX_AMOUNT_RAW + "=\"" + fieldSuffixAmountRaw + "\"");
|
||||
}
|
||||
fieldTypeAmountRaw = field.getType();
|
||||
if (!(fieldTypeAmountRaw instanceof LongValueFieldType)) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Field type \"" + this.getTypeName()
|
||||
+ "\": Dynamic field for " + PARAM_FIELD_SUFFIX_AMOUNT_RAW + "=\"" + fieldSuffixAmountRaw
|
||||
+ "\" must have type class extending LongValueFieldType");
|
||||
}
|
||||
}
|
||||
if (null == fieldTypeCurrency) {
|
||||
assert null != fieldSuffixCurrency : "How did we get here?";
|
||||
SchemaField field = schema.getFieldOrNull(POLY_FIELD_SEPARATOR + fieldSuffixCurrency);
|
||||
if (field == null) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Field type \"" + this.getTypeName()
|
||||
+ "\": Undefined dynamic field for " + PARAM_FIELD_SUFFIX_CURRENCY + "=\"" + fieldSuffixCurrency + "\"");
|
||||
}
|
||||
fieldTypeCurrency = field.getType();
|
||||
if (!(fieldTypeCurrency instanceof StrField)) {
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Field type \"" + this.getTypeName()
|
||||
+ "\": Dynamic field for " + PARAM_FIELD_SUFFIX_CURRENCY + "=\"" + fieldSuffixCurrency
|
||||
+ "\" must have type class of (or extending) StrField");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the currency config when resource loader initialized.
|
||||
*
|
||||
* @param resourceLoader The resource loader.
|
||||
*/
|
||||
@Override
|
||||
public void inform(ResourceLoader resourceLoader) {
|
||||
provider.inform(resourceLoader);
|
||||
boolean reloaded = provider.reload();
|
||||
if(!reloaded) {
|
||||
log.warn("Failed reloading currencies");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
|
||||
CurrencyValue value = CurrencyValue.parse(externalVal, defaultCurrency);
|
||||
CurrencyValue valueDefault;
|
||||
valueDefault = value.convertTo(provider, defaultCurrency);
|
||||
|
||||
return getRangeQuery(parser, field, valueDefault, valueDefault, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns a ValueSource over this field in which the numeric value for
|
||||
* each document represents the indexed value as converted to the default
|
||||
* currency for the field, normalized to its most granular form based
|
||||
* on the default fractional digits.
|
||||
* </p>
|
||||
* <p>
|
||||
* For example: If the default Currency specified for a field is
|
||||
* <code>USD</code>, then the values returned by this value source would
|
||||
* represent the equivilent number of "cents" (ie: value in dollars * 100)
|
||||
* after converting each document's native currency to USD -- because the
|
||||
* default fractional digits for <code>USD</code> is "<code>2</code>".
|
||||
* So for a document whose indexed value was currently equivilent to
|
||||
* "<code>5.43,USD</code>" using the the exchange provider for this field,
|
||||
* this ValueSource would return a value of "<code>543</code>"
|
||||
* </p>
|
||||
*
|
||||
* @see #PARAM_DEFAULT_CURRENCY
|
||||
* @see #DEFAULT_DEFAULT_CURRENCY
|
||||
* @see Currency#getDefaultFractionDigits
|
||||
* @see #getConvertedValueSource
|
||||
*/
|
||||
public RawCurrencyValueSource getValueSource(SchemaField field,
|
||||
QParser parser) {
|
||||
getAmountField(field).checkFieldCacheSource();
|
||||
getCurrencyField(field).checkFieldCacheSource();
|
||||
return new RawCurrencyValueSource(field, defaultCurrency, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns a ValueSource over this field in which the numeric value for
|
||||
* each document represents the value from the underlying
|
||||
* <code>RawCurrencyValueSource</code> as converted to the specified target
|
||||
* Currency.
|
||||
* </p>
|
||||
* <p>
|
||||
* For example: If the <code>targetCurrencyCode</code> param is set to
|
||||
* <code>USD</code>, then the values returned by this value source would
|
||||
* represent the equivilent number of dollars after converting each
|
||||
* document's raw value to <code>USD</code>. So for a document whose
|
||||
* indexed value was currently equivilent to "<code>5.43,USD</code>"
|
||||
* using the the exchange provider for this field, this ValueSource would
|
||||
* return a value of "<code>5.43</code>"
|
||||
* </p>
|
||||
*
|
||||
* @param targetCurrencyCode The target currency for the resulting value source, if null the defaultCurrency for this field type will be used
|
||||
* @param source the raw ValueSource to wrap
|
||||
* @see #PARAM_DEFAULT_CURRENCY
|
||||
* @see #DEFAULT_DEFAULT_CURRENCY
|
||||
* @see #getValueSource
|
||||
*/
|
||||
public ValueSource getConvertedValueSource(String targetCurrencyCode,
|
||||
RawCurrencyValueSource source) {
|
||||
if (null == targetCurrencyCode) {
|
||||
targetCurrencyCode = defaultCurrency;
|
||||
}
|
||||
return new ConvertedCurrencyValueSource(targetCurrencyCode,
|
||||
source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, String part1, String part2, final boolean minInclusive, final boolean maxInclusive) {
|
||||
final CurrencyValue p1 = CurrencyValue.parse(part1, defaultCurrency);
|
||||
final CurrencyValue p2 = CurrencyValue.parse(part2, defaultCurrency);
|
||||
|
||||
if (p1 != null && p2 != null && !p1.getCurrencyCode().equals(p2.getCurrencyCode())) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"Cannot parse range query " + part1 + " to " + part2 +
|
||||
": range queries only supported when upper and lower bound have same currency.");
|
||||
}
|
||||
|
||||
return getRangeQuery(parser, field, p1, p2, minInclusive, maxInclusive);
|
||||
}
|
||||
|
||||
public Query getRangeQuery(QParser parser, SchemaField field, final CurrencyValue p1, final CurrencyValue p2, final boolean minInclusive, final boolean maxInclusive) {
|
||||
String currencyCode = (p1 != null) ? p1.getCurrencyCode() :
|
||||
(p2 != null) ? p2.getCurrencyCode() : defaultCurrency;
|
||||
|
||||
// ValueSourceRangeFilter doesn't check exists(), so we have to
|
||||
final Filter docsWithValues = new QueryWrapperFilter(new FieldValueQuery(getAmountField(field).getName()));
|
||||
final Filter vsRangeFilter = new ValueSourceRangeFilter
|
||||
(new RawCurrencyValueSource(field, currencyCode, parser),
|
||||
p1 == null ? null : p1.getAmount() + "",
|
||||
p2 == null ? null : p2.getAmount() + "",
|
||||
minInclusive, maxInclusive);
|
||||
final BooleanQuery.Builder docsInRange = new BooleanQuery.Builder();
|
||||
docsInRange.add(docsWithValues, Occur.FILTER);
|
||||
docsInRange.add(vsRangeFilter, Occur.FILTER);
|
||||
|
||||
return new SolrConstantScoreQuery(new QueryWrapperFilter(docsInRange.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortField getSortField(SchemaField field, boolean reverse) {
|
||||
// Convert all values to default currency for sorting.
|
||||
return (new RawCurrencyValueSource(field, defaultCurrency, null)).getSortField(reverse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getUninversionType(SchemaField sf) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(TextResponseWriter writer, String name, IndexableField field) throws IOException {
|
||||
writer.writeStr(name, field.stringValue(), true);
|
||||
}
|
||||
|
||||
public ExchangeRateProvider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A value source whose values represent the "normal" values
|
||||
* in the specified target currency.
|
||||
* </p>
|
||||
* @see RawCurrencyValueSource
|
||||
*/
|
||||
class ConvertedCurrencyValueSource extends ValueSource {
|
||||
private final Currency targetCurrency;
|
||||
private final RawCurrencyValueSource source;
|
||||
private final double rate;
|
||||
public ConvertedCurrencyValueSource(String targetCurrencyCode,
|
||||
RawCurrencyValueSource source) {
|
||||
this.source = source;
|
||||
this.targetCurrency = getCurrency(targetCurrencyCode);
|
||||
if (null == targetCurrency) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + targetCurrencyCode);
|
||||
}
|
||||
// the target digits & currency of our source,
|
||||
// become the source digits & currency of ourselves
|
||||
this.rate = provider.getExchangeRate
|
||||
(source.getTargetCurrency().getCurrencyCode(),
|
||||
targetCurrency.getCurrencyCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionValues getValues(Map context, LeafReaderContext reader)
|
||||
throws IOException {
|
||||
final FunctionValues amounts = source.getValues(context, reader);
|
||||
// the target digits & currency of our source,
|
||||
// become the source digits & currency of ourselves
|
||||
final String sourceCurrencyCode = source.getTargetCurrency().getCurrencyCode();
|
||||
final double divisor = Math.pow(10D, targetCurrency.getDefaultFractionDigits());
|
||||
return new FunctionValues() {
|
||||
@Override
|
||||
public boolean exists(int doc) throws IOException {
|
||||
return amounts.exists(doc);
|
||||
}
|
||||
@Override
|
||||
public long longVal(int doc) throws IOException {
|
||||
return (long) doubleVal(doc);
|
||||
}
|
||||
@Override
|
||||
public int intVal(int doc) throws IOException {
|
||||
return (int) doubleVal(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleVal(int doc) throws IOException {
|
||||
return CurrencyValue.convertAmount(rate, sourceCurrencyCode, amounts.longVal(doc), targetCurrency.getCurrencyCode()) / divisor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatVal(int doc) throws IOException {
|
||||
return CurrencyValue.convertAmount(rate, sourceCurrencyCode, amounts.longVal(doc), targetCurrency.getCurrencyCode()) / ((float)divisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String strVal(int doc) throws IOException {
|
||||
return Double.toString(doubleVal(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int doc) throws IOException {
|
||||
return name() + '(' + strVal(doc) + ')';
|
||||
}
|
||||
};
|
||||
}
|
||||
public String name() {
|
||||
return "currency";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return name() + "(" + source.getField().getName() + "," + targetCurrency.getCurrencyCode()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ConvertedCurrencyValueSource that = (ConvertedCurrencyValueSource) o;
|
||||
|
||||
return !(source != null ? !source.equals(that.source) : that.source != null) &&
|
||||
(rate == that.rate) &&
|
||||
!(targetCurrency != null ? !targetCurrency.equals(that.targetCurrency) : that.targetCurrency != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = targetCurrency != null ? targetCurrency.hashCode() : 0;
|
||||
result = 31 * result + (source != null ? source.hashCode() : 0);
|
||||
result = 31 * (int) Double.doubleToLongBits(rate);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A value source whose values represent the "raw" (ie: normalized using
|
||||
* the number of default fractional digits) values in the specified
|
||||
* target currency).
|
||||
* </p>
|
||||
* <p>
|
||||
* For example: if the specified target currency is "<code>USD</code>"
|
||||
* then the numeric values are the number of pennies in the value
|
||||
* (ie: <code>$n * 100</code>) since the number of default fractional
|
||||
* digits for <code>USD</code> is "<code>2</code>")
|
||||
* </p>
|
||||
* @see ConvertedCurrencyValueSource
|
||||
*/
|
||||
class RawCurrencyValueSource extends ValueSource {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Currency targetCurrency;
|
||||
private ValueSource currencyValues;
|
||||
private ValueSource amountValues;
|
||||
private final SchemaField sf;
|
||||
|
||||
public RawCurrencyValueSource(SchemaField sfield, String targetCurrencyCode, QParser parser) {
|
||||
this.sf = sfield;
|
||||
this.targetCurrency = getCurrency(targetCurrencyCode);
|
||||
if (null == targetCurrency) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + targetCurrencyCode);
|
||||
}
|
||||
|
||||
SchemaField amountField = getAmountField(sf);
|
||||
SchemaField currencyField = getCurrencyField(sf);
|
||||
|
||||
currencyValues = currencyField.getType().getValueSource(currencyField, parser);
|
||||
amountValues = amountField.getType().getValueSource(amountField, parser);
|
||||
}
|
||||
|
||||
public SchemaField getField() { return sf; }
|
||||
public Currency getTargetCurrency() { return targetCurrency; }
|
||||
|
||||
@Override
|
||||
public FunctionValues getValues(Map context, LeafReaderContext reader) throws IOException {
|
||||
final FunctionValues amounts = amountValues.getValues(context, reader);
|
||||
final FunctionValues currencies = currencyValues.getValues(context, reader);
|
||||
|
||||
return new FunctionValues() {
|
||||
private static final int MAX_CURRENCIES_TO_CACHE = 256;
|
||||
private final int[] fractionDigitCache = new int[MAX_CURRENCIES_TO_CACHE];
|
||||
private final String[] currencyOrdToCurrencyCache = new String[MAX_CURRENCIES_TO_CACHE];
|
||||
private final double[] exchangeRateCache = new double[MAX_CURRENCIES_TO_CACHE];
|
||||
private int targetFractionDigits = -1;
|
||||
private int targetCurrencyOrd = -1;
|
||||
private boolean initializedCache;
|
||||
|
||||
private String getDocCurrencyCode(int doc, int currencyOrd) throws IOException {
|
||||
if (currencyOrd < MAX_CURRENCIES_TO_CACHE) {
|
||||
String currency = currencyOrdToCurrencyCache[currencyOrd];
|
||||
|
||||
if (currency == null) {
|
||||
currencyOrdToCurrencyCache[currencyOrd] = currency = currencies.strVal(doc);
|
||||
}
|
||||
|
||||
if (currency == null) {
|
||||
currency = defaultCurrency;
|
||||
}
|
||||
|
||||
if (targetCurrencyOrd == -1 &&
|
||||
currency.equals(targetCurrency.getCurrencyCode() )) {
|
||||
targetCurrencyOrd = currencyOrd;
|
||||
}
|
||||
|
||||
return currency;
|
||||
} else {
|
||||
return currencies.strVal(doc);
|
||||
}
|
||||
}
|
||||
/** throws a (Server Error) SolrException if the code is not valid */
|
||||
private Currency getDocCurrency(int doc, int currencyOrd) throws IOException {
|
||||
String code = getDocCurrencyCode(doc, currencyOrd);
|
||||
Currency c = getCurrency(code);
|
||||
if (null == c) {
|
||||
throw new SolrException
|
||||
(SolrException.ErrorCode.SERVER_ERROR,
|
||||
"Currency code of document is not supported by this JVM: "+code);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(int doc) throws IOException {
|
||||
return amounts.exists(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longVal(int doc) throws IOException {
|
||||
long amount = amounts.longVal(doc);
|
||||
// bail fast using whatever amounts defaults to if no value
|
||||
// (if we don't do this early, currencyOrd may be < 0,
|
||||
// causing index bounds exception
|
||||
if ( ! exists(doc) ) {
|
||||
return amount;
|
||||
}
|
||||
|
||||
if (!initializedCache) {
|
||||
for (int i = 0; i < fractionDigitCache.length; i++) {
|
||||
fractionDigitCache[i] = -1;
|
||||
}
|
||||
|
||||
initializedCache = true;
|
||||
}
|
||||
|
||||
int currencyOrd = currencies.ordVal(doc);
|
||||
|
||||
if (currencyOrd == targetCurrencyOrd) {
|
||||
return amount;
|
||||
}
|
||||
|
||||
double exchangeRate;
|
||||
int sourceFractionDigits;
|
||||
|
||||
if (targetFractionDigits == -1) {
|
||||
targetFractionDigits = targetCurrency.getDefaultFractionDigits();
|
||||
}
|
||||
|
||||
if (currencyOrd < MAX_CURRENCIES_TO_CACHE) {
|
||||
exchangeRate = exchangeRateCache[currencyOrd];
|
||||
|
||||
if (exchangeRate <= 0.0) {
|
||||
String sourceCurrencyCode = getDocCurrencyCode(doc, currencyOrd);
|
||||
exchangeRate = exchangeRateCache[currencyOrd] = provider.getExchangeRate(sourceCurrencyCode, targetCurrency.getCurrencyCode());
|
||||
}
|
||||
|
||||
sourceFractionDigits = fractionDigitCache[currencyOrd];
|
||||
|
||||
if (sourceFractionDigits == -1) {
|
||||
sourceFractionDigits = fractionDigitCache[currencyOrd] = getDocCurrency(doc, currencyOrd).getDefaultFractionDigits();
|
||||
}
|
||||
} else {
|
||||
Currency source = getDocCurrency(doc, currencyOrd);
|
||||
exchangeRate = provider.getExchangeRate(source.getCurrencyCode(), targetCurrency.getCurrencyCode());
|
||||
sourceFractionDigits = source.getDefaultFractionDigits();
|
||||
}
|
||||
|
||||
return CurrencyValue.convertAmount(exchangeRate, sourceFractionDigits, amount, targetFractionDigits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intVal(int doc) throws IOException {
|
||||
return (int) longVal(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleVal(int doc) throws IOException {
|
||||
return (double) longVal(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatVal(int doc) throws IOException {
|
||||
return (float) longVal(doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String strVal(int doc) throws IOException {
|
||||
return Long.toString(longVal(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(int doc) throws IOException {
|
||||
return name() + '(' + amounts.toString(doc) + ',' + currencies.toString(doc) + ')';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return "rawcurrency";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return name() + "(" + sf.getName() +
|
||||
",target="+targetCurrency.getCurrencyCode()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
RawCurrencyValueSource that = (RawCurrencyValueSource) o;
|
||||
|
||||
return !(amountValues != null ? !amountValues.equals(that.amountValues) : that.amountValues != null) &&
|
||||
!(currencyValues != null ? !currencyValues.equals(that.currencyValues) : that.currencyValues != null) &&
|
||||
!(targetCurrency != null ? !targetCurrency.equals(that.targetCurrency) : that.targetCurrency != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = targetCurrency != null ? targetCurrency.hashCode() : 0;
|
||||
result = 31 * result + (currencyValues != null ? currencyValues.hashCode() : 0);
|
||||
result = 31 * result + (amountValues != null ? amountValues.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Currency field value, which includes a long amount and ISO currency code.
|
||||
*/
|
||||
static class CurrencyValue {
|
||||
private long amount;
|
||||
private String currencyCode;
|
||||
|
||||
/**
|
||||
* Constructs a new currency value.
|
||||
*
|
||||
* @param amount The amount.
|
||||
* @param currencyCode The currency code.
|
||||
*/
|
||||
public CurrencyValue(long amount, String currencyCode) {
|
||||
this.amount = amount;
|
||||
this.currencyCode = currencyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new currency value by parsing the specific input.
|
||||
* <p/>
|
||||
* Currency values are expected to be in the format <amount>,<currency code>,
|
||||
* for example, "500,USD" would represent 5 U.S. Dollars.
|
||||
* <p/>
|
||||
* If no currency code is specified, the default is assumed.
|
||||
*
|
||||
* @param externalVal The value to parse.
|
||||
* @param defaultCurrency The default currency.
|
||||
* @return The parsed CurrencyValue.
|
||||
*/
|
||||
public static CurrencyValue parse(String externalVal, String defaultCurrency) {
|
||||
if (externalVal == null) {
|
||||
return null;
|
||||
}
|
||||
String amount = externalVal;
|
||||
String code = defaultCurrency;
|
||||
|
||||
if (externalVal.contains(",")) {
|
||||
String[] amountAndCode = externalVal.split(",");
|
||||
amount = amountAndCode[0];
|
||||
code = amountAndCode[1];
|
||||
}
|
||||
|
||||
if (amount.equals("*")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Currency currency = getCurrency(code);
|
||||
|
||||
if (currency == null) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + code);
|
||||
}
|
||||
|
||||
try {
|
||||
double value = Double.parseDouble(amount);
|
||||
long currencyValue = Math.round(value * Math.pow(10.0, currency.getDefaultFractionDigits()));
|
||||
|
||||
return new CurrencyValue(currencyValue, code);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of the CurrencyValue.
|
||||
*
|
||||
* @return The amount.
|
||||
*/
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ISO currency code of the CurrencyValue.
|
||||
*
|
||||
* @return The currency code.
|
||||
*/
|
||||
public String getCurrencyCode() {
|
||||
return currencyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a currency conversion & unit conversion.
|
||||
*
|
||||
* @param exchangeRates Exchange rates to apply.
|
||||
* @param sourceCurrencyCode The source currency code.
|
||||
* @param sourceAmount The source amount.
|
||||
* @param targetCurrencyCode The target currency code.
|
||||
* @return The converted indexable units after the exchange rate and currency fraction digits are applied.
|
||||
*/
|
||||
public static long convertAmount(ExchangeRateProvider exchangeRates, String sourceCurrencyCode, long sourceAmount, String targetCurrencyCode) {
|
||||
double exchangeRate = exchangeRates.getExchangeRate(sourceCurrencyCode, targetCurrencyCode);
|
||||
return convertAmount(exchangeRate, sourceCurrencyCode, sourceAmount, targetCurrencyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a currency conversion & unit conversion.
|
||||
*
|
||||
* @param exchangeRate Exchange rate to apply.
|
||||
* @param sourceFractionDigits The fraction digits of the source.
|
||||
* @param sourceAmount The source amount.
|
||||
* @param targetFractionDigits The fraction digits of the target.
|
||||
* @return The converted indexable units after the exchange rate and currency fraction digits are applied.
|
||||
*/
|
||||
public static long convertAmount(final double exchangeRate, final int sourceFractionDigits, final long sourceAmount, final int targetFractionDigits) {
|
||||
int digitDelta = targetFractionDigits - sourceFractionDigits;
|
||||
double value = ((double) sourceAmount * exchangeRate);
|
||||
|
||||
if (digitDelta != 0) {
|
||||
if (digitDelta < 0) {
|
||||
for (int i = 0; i < -digitDelta; i++) {
|
||||
value *= 0.1;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < digitDelta; i++) {
|
||||
value *= 10.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (long) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a currency conversion & unit conversion.
|
||||
*
|
||||
* @param exchangeRate Exchange rate to apply.
|
||||
* @param sourceCurrencyCode The source currency code.
|
||||
* @param sourceAmount The source amount.
|
||||
* @param targetCurrencyCode The target currency code.
|
||||
* @return The converted indexable units after the exchange rate and currency fraction digits are applied.
|
||||
*/
|
||||
public static long convertAmount(double exchangeRate, String sourceCurrencyCode, long sourceAmount, String targetCurrencyCode) {
|
||||
if (targetCurrencyCode.equals(sourceCurrencyCode)) {
|
||||
return sourceAmount;
|
||||
}
|
||||
|
||||
int sourceFractionDigits = Currency.getInstance(sourceCurrencyCode).getDefaultFractionDigits();
|
||||
Currency targetCurrency = Currency.getInstance(targetCurrencyCode);
|
||||
int targetFractionDigits = targetCurrency.getDefaultFractionDigits();
|
||||
return convertAmount(exchangeRate, sourceFractionDigits, sourceAmount, targetFractionDigits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new CurrencyValue that is the conversion of this CurrencyValue to the specified currency.
|
||||
*
|
||||
* @param exchangeRates The exchange rate provider.
|
||||
* @param targetCurrencyCode The target currency code to convert this CurrencyValue to.
|
||||
* @return The converted CurrencyValue.
|
||||
*/
|
||||
public CurrencyValue convertTo(ExchangeRateProvider exchangeRates, String targetCurrencyCode) {
|
||||
return new CurrencyValue(convertAmount(exchangeRates, this.getCurrencyCode(), this.getAmount(), targetCurrencyCode), targetCurrencyCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(amount) + "," + currencyCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.analysis.util.ResourceLoader;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Configuration for currency. Provides currency exchange rates.
|
||||
*/
|
||||
class FileExchangeRateProvider implements ExchangeRateProvider {
|
||||
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
protected static final String PARAM_CURRENCY_CONFIG = "currencyConfig";
|
||||
|
||||
// Exchange rate map, maps Currency Code -> Currency Code -> Rate
|
||||
private Map<String, Map<String, Double>> rates = new HashMap<>();
|
||||
|
||||
private String currencyConfigFile;
|
||||
private ResourceLoader loader;
|
||||
|
||||
/**
|
||||
* Returns the currently known exchange rate between two currencies. If a direct rate has been loaded,
|
||||
* it is used. Otherwise, if a rate is known to convert the target currency to the source, the inverse
|
||||
* exchange rate is computed.
|
||||
*
|
||||
* @param sourceCurrencyCode The source currency being converted from.
|
||||
* @param targetCurrencyCode The target currency being converted to.
|
||||
* @return The exchange rate.
|
||||
* @throws SolrException if the requested currency pair cannot be found
|
||||
*/
|
||||
@Override
|
||||
public double getExchangeRate(String sourceCurrencyCode, String targetCurrencyCode) {
|
||||
if (sourceCurrencyCode == null || targetCurrencyCode == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot get exchange rate; currency was null.");
|
||||
}
|
||||
|
||||
if (sourceCurrencyCode.equals(targetCurrencyCode)) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
Double directRate = lookupRate(sourceCurrencyCode, targetCurrencyCode);
|
||||
|
||||
if (directRate != null) {
|
||||
return directRate;
|
||||
}
|
||||
|
||||
Double symmetricRate = lookupRate(targetCurrencyCode, sourceCurrencyCode);
|
||||
|
||||
if (symmetricRate != null) {
|
||||
return 1.0 / symmetricRate;
|
||||
}
|
||||
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No available conversion rate between " + sourceCurrencyCode + " to " + targetCurrencyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the current known rate, if any, between the source and target currencies.
|
||||
*
|
||||
* @param sourceCurrencyCode The source currency being converted from.
|
||||
* @param targetCurrencyCode The target currency being converted to.
|
||||
* @return The exchange rate, or null if no rate has been registered.
|
||||
*/
|
||||
private Double lookupRate(String sourceCurrencyCode, String targetCurrencyCode) {
|
||||
Map<String, Double> rhs = rates.get(sourceCurrencyCode);
|
||||
|
||||
if (rhs != null) {
|
||||
return rhs.get(targetCurrencyCode);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the specified exchange rate.
|
||||
*
|
||||
* @param ratesMap The map to add rate to
|
||||
* @param sourceCurrencyCode The source currency.
|
||||
* @param targetCurrencyCode The target currency.
|
||||
* @param rate The known exchange rate.
|
||||
*/
|
||||
private void addRate(Map<String, Map<String, Double>> ratesMap, String sourceCurrencyCode, String targetCurrencyCode, double rate) {
|
||||
Map<String, Double> rhs = ratesMap.get(sourceCurrencyCode);
|
||||
|
||||
if (rhs == null) {
|
||||
rhs = new HashMap<>();
|
||||
ratesMap.put(sourceCurrencyCode, rhs);
|
||||
}
|
||||
|
||||
rhs.put(targetCurrencyCode, rate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FileExchangeRateProvider that = (FileExchangeRateProvider) o;
|
||||
|
||||
return !(rates != null ? !rates.equals(that.rates) : that.rates != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return rates != null ? rates.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "["+this.getClass().getName()+" : " + rates.size() + " rates.]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> listAvailableCurrencies() {
|
||||
Set<String> currencies = new HashSet<>();
|
||||
for(String from : rates.keySet()) {
|
||||
currencies.add(from);
|
||||
for(String to : rates.get(from).keySet()) {
|
||||
currencies.add(to);
|
||||
}
|
||||
}
|
||||
return currencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reload() throws SolrException {
|
||||
InputStream is = null;
|
||||
Map<String, Map<String, Double>> tmpRates = new HashMap<>();
|
||||
try {
|
||||
log.debug("Reloading exchange rates from file "+this.currencyConfigFile);
|
||||
|
||||
is = loader.openResource(currencyConfigFile);
|
||||
javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
dbf.setXIncludeAware(true);
|
||||
dbf.setNamespaceAware(true);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "XML parser doesn't support XInclude option", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Document doc = dbf.newDocumentBuilder().parse(is);
|
||||
XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||
XPath xpath = xpathFactory.newXPath();
|
||||
|
||||
// Parse exchange rates.
|
||||
NodeList nodes = (NodeList) xpath.evaluate("/currencyConfig/rates/rate", doc, XPathConstants.NODESET);
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node rateNode = nodes.item(i);
|
||||
NamedNodeMap attributes = rateNode.getAttributes();
|
||||
Node from = attributes.getNamedItem("from");
|
||||
Node to = attributes.getNamedItem("to");
|
||||
Node rate = attributes.getNamedItem("rate");
|
||||
|
||||
if (from == null || to == null || rate == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Exchange rate missing attributes (required: from, to, rate) " + rateNode);
|
||||
}
|
||||
|
||||
String fromCurrency = from.getNodeValue();
|
||||
String toCurrency = to.getNodeValue();
|
||||
Double exchangeRate;
|
||||
|
||||
if (null == CurrencyFieldType.getCurrency(fromCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'from' currency not supported in this JVM: " + fromCurrency);
|
||||
}
|
||||
if (null == CurrencyFieldType.getCurrency(toCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'to' currency not supported in this JVM: " + toCurrency);
|
||||
}
|
||||
|
||||
try {
|
||||
exchangeRate = Double.parseDouble(rate.getNodeValue());
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Could not parse exchange rate: " + rateNode, e);
|
||||
}
|
||||
|
||||
addRate(tmpRates, fromCurrency, toCurrency, exchangeRate);
|
||||
}
|
||||
} catch (SAXException | XPathExpressionException | ParserConfigurationException | IOException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error while opening Currency configuration file "+currencyConfigFile, e);
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Atomically swap in the new rates map, if it loaded successfully
|
||||
this.rates = tmpRates;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Map<String,String> params) throws SolrException {
|
||||
this.currencyConfigFile = params.get(PARAM_CURRENCY_CONFIG);
|
||||
if(currencyConfigFile == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "Missing required configuration "+PARAM_CURRENCY_CONFIG);
|
||||
}
|
||||
|
||||
// Removing config params custom to us
|
||||
params.remove(PARAM_CURRENCY_CONFIG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inform(ResourceLoader loader) throws SolrException {
|
||||
if(loader == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Needs ResourceLoader in order to load config file");
|
||||
}
|
||||
this.loader = loader;
|
||||
reload();
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* Exchange Rates Provider for {@link CurrencyField} capable of fetching &
|
||||
* Exchange Rates Provider for {@link CurrencyField} and {@link CurrencyFieldType} capable of fetching &
|
||||
* parsing the freely available exchange rates from openexchangerates.org
|
||||
* </p>
|
||||
* <p>
|
||||
|
|
|
@ -47,7 +47,7 @@ import org.apache.lucene.util.BytesRefBuilder;
|
|||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.request.SolrRequestInfo;
|
||||
import org.apache.solr.schema.CurrencyField;
|
||||
import org.apache.solr.schema.CurrencyFieldType;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.schema.StrField;
|
||||
|
@ -444,11 +444,11 @@ public abstract class ValueSourceParser implements NamedListInitializedPlugin {
|
|||
|
||||
String fieldName = fp.parseArg();
|
||||
SchemaField f = fp.getReq().getSchema().getField(fieldName);
|
||||
if (! (f.getType() instanceof CurrencyField)) {
|
||||
if (! (f.getType() instanceof CurrencyFieldType)) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"Currency function input must be the name of a CurrencyField: " + fieldName);
|
||||
"Currency function input must be the name of a CurrencyFieldType: " + fieldName);
|
||||
}
|
||||
CurrencyField ft = (CurrencyField) f.getType();
|
||||
CurrencyFieldType ft = (CurrencyFieldType) f.getType();
|
||||
String code = fp.hasMoreArguments() ? fp.parseArg() : null;
|
||||
return ft.getConvertedValueSource(code, ft.getValueSource(f, fp));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currency-ft-amount-suffix" version="1.4">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" multiValued="false"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: amountLongSuffix not allowed -->
|
||||
<fieldType name="currency" class="solr.CurrencyField" amountLongSuffix="_l" multiValued="false"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dyanmicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currency-ft-code-suffix" version="1.4">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: codeStrSuffix not allowed -->
|
||||
<fieldType name="currency" class="solr.CurrencyField" codeStrSuffix="_s" multiValued="false"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dyanmicField name="*_s" type="string" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<schema name="bad-schema-currency-ft-oer-norates" version="1.4">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<!-- BEGIN BAD STUFF: multiValued -->
|
||||
<!-- BEGIN BAD STUFF: no rates-->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyField"
|
||||
providerClass="solr.OpenExchangeRatesOrgProvider"
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-bogus-amount-suffix" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: bogus amount field suffix -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_NOT_THERE" codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-bogus-code-suffix" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: bogus code field suffix -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_l" codeStrSuffix="_NOT_THERE"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-dynamic-multivalued" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_l" codeStrSuffix="_s"/>
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: multiValued="true" -->
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true" multiValued="true"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-ft-bogus-code-in-xml" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: bad-currency.xml has bogus code-->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyFieldType"
|
||||
defaultCurrency="USD"
|
||||
currencyConfig="bad-currency.xml"
|
||||
multiValued="false"
|
||||
amountLongSuffix="_l"
|
||||
codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-ft-bogus-default-code" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: defaultCurrency -->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyFieldType"
|
||||
defaultCurrency="HOSS"
|
||||
currencyConfig="currency.xml"
|
||||
multiValued="false"
|
||||
amountLongSuffix="_l"
|
||||
codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-ft-multivalued" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: multiValued -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="true"
|
||||
amountLongSuffix="_l" codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-ft-oer-norates" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: no rates -->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyFieldType"
|
||||
providerClass="solr.OpenExchangeRatesOrgProvider"
|
||||
multiValued="false"
|
||||
amountLongSuffix="_l"
|
||||
codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-missing-amount-suffix" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: missing amountLongSuffix -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-missing-code-suffix" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: missing codeStrSuffix -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_l"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-multivalued" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml"
|
||||
amountLongSuffix="_l" codeStrSuffix="_s"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: multiValued="true" -->
|
||||
<field name="money" type="currency" indexed="true" stored="true" multiValued="true"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-wrong-amount-ft" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: code dynamic field type is wrong -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_s" codeStrSuffix="_s"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_s" type="string" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currencyfieldtype-wrong-code-ft" version="1.6">
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<fieldType name="plong" class="solr.LongPointField" docValues="true"/>
|
||||
|
||||
<!-- BEGIN BAD STUFF: code dynamic field type is wrong -->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
|
||||
amountLongSuffix="_l" codeStrSuffix="_l"/>
|
||||
<!-- END BAD STUFF -->
|
||||
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
|
||||
<dynamicField name="*_l" type="plong" multiValued="false"/>
|
||||
<dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -451,6 +451,17 @@
|
|||
multiValued="false"
|
||||
providerClass="solr.OpenExchangeRatesOrgProvider"
|
||||
ratesFileLocation="open-exchange-rates.json"/>
|
||||
<fieldType name="currency_CFT" class="solr.CurrencyFieldType" amountLongSuffix="_l1_ns" codeStrSuffix="_s1"
|
||||
currencyConfig="currency.xml" multiValued="false"/>
|
||||
<fieldType name="mock_currency_CFT" class="solr.CurrencyFieldType" amountLongSuffix="_l1_ns" codeStrSuffix="_s1"
|
||||
providerClass="solr.MockExchangeRateProvider" foo="bar" multiValued="false"/>
|
||||
<fieldType name="oer_currency_CFT"
|
||||
class="solr.CurrencyFieldType"
|
||||
amountLongSuffix="_l1_ns"
|
||||
codeStrSuffix="_s1_ns"
|
||||
multiValued="false"
|
||||
providerClass="solr.OpenExchangeRatesOrgProvider"
|
||||
ratesFileLocation="open-exchange-rates.json"/>
|
||||
|
||||
<!-- omitPositions example -->
|
||||
<fieldType name="nopositions" class="solr.TextField" omitPositions="true">
|
||||
|
@ -539,6 +550,9 @@
|
|||
<field name="amount" type="currency" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="mock_amount" type="mock_currency" indexed="true" stored="true"/>
|
||||
<field name="oer_amount" type="oer_currency" indexed="true" stored="true"/>
|
||||
<field name="amount_CFT" type="currency_CFT" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="mock_amount_CFT" type="mock_currency_CFT" indexed="true" stored="true"/>
|
||||
<field name="oer_amount_CFT" type="oer_currency_CFT" indexed="true" stored="true"/>
|
||||
|
||||
<!-- test different combinations of indexed and stored -->
|
||||
<field name="bind" type="boolean" indexed="true" stored="false"/>
|
||||
|
@ -652,8 +666,10 @@
|
|||
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_s1" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<dynamicField name="*_s1_ns" type="string" indexed="true" stored="false" multiValued="false"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l1" type="long" indexed="true" stored="true" multiValued="false"/>
|
||||
<dynamicField name="*_l1_ns" type="long" indexed="true" stored="false" multiValued="false"/>
|
||||
<dynamicField name="*_t" type="text" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_b1" type="boolean" indexed="true" stored="true" multiValued="false"/>
|
||||
|
|
|
@ -68,14 +68,22 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
|
|||
doTest("bad-schema-currency-ft-multivalued.xml",
|
||||
"types can not be multiValued: currency");
|
||||
doTest("bad-schema-currency-multivalued.xml",
|
||||
"Fields can not be multiValued: money");
|
||||
"fields can not be multiValued: money");
|
||||
doTest("bad-schema-currency-dynamic-multivalued.xml",
|
||||
"Fields can not be multiValued: *_c");
|
||||
"fields can not be multiValued: *_c");
|
||||
doTest("bad-schema-currencyfieldtype-ft-multivalued.xml",
|
||||
"types can not be multiValued: currency");
|
||||
doTest("bad-schema-currencyfieldtype-multivalued.xml",
|
||||
"fields can not be multiValued: money");
|
||||
doTest("bad-schema-currencyfieldtype-dynamic-multivalued.xml",
|
||||
"fields can not be multiValued: *_c");
|
||||
}
|
||||
|
||||
public void testCurrencyOERNoRates() throws Exception {
|
||||
doTest("bad-schema-currency-ft-oer-norates.xml",
|
||||
"ratesFileLocation");
|
||||
doTest("bad-schema-currencyfieldtype-ft-oer-norates.xml",
|
||||
"ratesFileLocation");
|
||||
}
|
||||
|
||||
public void testCurrencyBogusCode() throws Exception {
|
||||
|
@ -83,6 +91,35 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
|
|||
"HOSS");
|
||||
doTest("bad-schema-currency-ft-bogus-code-in-xml.xml",
|
||||
"HOSS");
|
||||
doTest("bad-schema-currencyfieldtype-ft-bogus-default-code.xml",
|
||||
"HOSS");
|
||||
doTest("bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml",
|
||||
"HOSS");
|
||||
}
|
||||
|
||||
public void testCurrencyDisallowedSuffixParams() throws Exception {
|
||||
doTest("bad-schema-currency-ft-code-suffix.xml",
|
||||
"Unknown parameter(s)");
|
||||
doTest("bad-schema-currency-ft-amount-suffix.xml",
|
||||
"Unknown parameter(s)");
|
||||
}
|
||||
|
||||
public void testCurrencyBogusSuffixes() throws Exception {
|
||||
doTest("bad-schema-currencyfieldtype-bogus-code-suffix.xml",
|
||||
"Undefined dynamic field for codeStrSuffix");
|
||||
doTest("bad-schema-currencyfieldtype-bogus-amount-suffix.xml",
|
||||
"Undefined dynamic field for amountLongSuffix");
|
||||
doTest("bad-schema-currencyfieldtype-wrong-code-ft.xml",
|
||||
"Dynamic field for codeStrSuffix=\"_l\" must have type class of (or extending) StrField");
|
||||
doTest("bad-schema-currencyfieldtype-wrong-amount-ft.xml",
|
||||
"Dynamic field for amountLongSuffix=\"_s\" must have type class extending LongValueFieldType");
|
||||
}
|
||||
|
||||
public void testCurrencyMissingSuffixes() throws Exception {
|
||||
doTest("bad-schema-currencyfieldtype-missing-code-suffix.xml",
|
||||
"Missing required param codeStrSuffix");
|
||||
doTest("bad-schema-currencyfieldtype-missing-amount-suffix.xml",
|
||||
"Missing required param amountLongSuffix");
|
||||
}
|
||||
|
||||
public void testPerFieldtypeSimButNoSchemaSimFactory() throws Exception {
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.solr.schema;
|
||||
|
||||
/**
|
||||
* Tests currency field type using OpenExchangeRatesOrgProvider.
|
||||
*/
|
||||
public class CurrencyFieldOpenExchangeTest extends AbstractCurrencyFieldTest {
|
||||
|
||||
public String field() {
|
||||
return "oer_amount";
|
||||
}
|
||||
}
|
|
@ -14,12 +14,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
|
@ -29,13 +33,28 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests currency field type.
|
||||
* @see #field
|
||||
*/
|
||||
@Ignore("Abstract base class with test methods")
|
||||
public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
||||
/** Tests CurrencyField and CurrencyFieldType. */
|
||||
public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
|
||||
private final String fieldName;
|
||||
private final Class<? extends ExchangeRateProvider> expectedProviderClass;
|
||||
|
||||
public CurrencyFieldTypeTest(String fieldName, Class<? extends ExchangeRateProvider> expectedProviderClass) {
|
||||
this.fieldName = fieldName;
|
||||
this.expectedProviderClass = expectedProviderClass;
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{"amount", FileExchangeRateProvider.class}, // CurrencyField
|
||||
{"mock_amount", MockExchangeRateProvider.class}, // CurrencyField
|
||||
{"oer_amount", OpenExchangeRatesOrgProvider.class}, // CurrencyField
|
||||
{"amount_CFT", FileExchangeRateProvider.class}, // CurrencyFieldType
|
||||
{"mock_amount_CFT", MockExchangeRateProvider.class}, // CurrencyFieldType
|
||||
{"oer_amount_CFT", OpenExchangeRatesOrgProvider.class} // CurrencyFieldType
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* "Assumes" that the specified list of currency codes are
|
||||
* supported in this JVM
|
||||
|
@ -59,44 +78,50 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
initCore("solrconfig.xml", "schema.xml");
|
||||
}
|
||||
|
||||
/** The field name to use in all tests */
|
||||
public abstract String field();
|
||||
|
||||
@Test
|
||||
public void testCurrencySchema() throws Exception {
|
||||
IndexSchema schema = h.getCore().getLatestSchema();
|
||||
|
||||
SchemaField amount = schema.getField(field());
|
||||
SchemaField amount = schema.getField(fieldName);
|
||||
assertNotNull(amount);
|
||||
assertTrue(amount.isPolyField());
|
||||
|
||||
CurrencyFieldType type = (CurrencyFieldType)amount.getType();
|
||||
String currencyDynamicField
|
||||
= "*" + (type instanceof CurrencyField ? FieldType.POLY_FIELD_SEPARATOR : "") + type.fieldSuffixCurrency;
|
||||
String amountDynamicField
|
||||
= "*" + (type instanceof CurrencyField ? FieldType.POLY_FIELD_SEPARATOR : "") + type.fieldSuffixAmountRaw;
|
||||
|
||||
SchemaField[] dynFields = schema.getDynamicFieldPrototypes();
|
||||
boolean seenCurrency = false;
|
||||
boolean seenAmount = false;
|
||||
|
||||
for (SchemaField dynField : dynFields) {
|
||||
if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + CurrencyField.FIELD_SUFFIX_CURRENCY)) {
|
||||
seenCurrency = true;
|
||||
if (dynField.getName().equals(amountDynamicField)) {
|
||||
seenAmount = true;
|
||||
}
|
||||
|
||||
if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + CurrencyField.FIELD_SUFFIX_AMOUNT_RAW)) {
|
||||
seenAmount = true;
|
||||
if (dynField.getName().equals(currencyDynamicField)) {
|
||||
seenCurrency = true;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue("Didn't find the expected currency code dynamic field", seenCurrency);
|
||||
assertTrue("Didn't find the expected value dynamic field", seenAmount);
|
||||
assertTrue("Didn't find the expected currency code dynamic field " + currencyDynamicField, seenCurrency);
|
||||
assertTrue("Didn't find the expected value dynamic field " + amountDynamicField, seenAmount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrencyFieldType() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
SolrCore core = h.getCore();
|
||||
IndexSchema schema = core.getLatestSchema();
|
||||
SchemaField amount = schema.getField(field());
|
||||
SchemaField amount = schema.getField(fieldName);
|
||||
assertNotNull(amount);
|
||||
assertTrue(field() + " is not a poly field", amount.isPolyField());
|
||||
assertTrue(fieldName + " is not a poly field", amount.isPolyField());
|
||||
FieldType tmp = amount.getType();
|
||||
assertTrue(tmp instanceof CurrencyField);
|
||||
assertTrue(fieldName + " is not an instance of CurrencyFieldType", tmp instanceof CurrencyFieldType);
|
||||
String currencyValue = "1.50,EUR";
|
||||
List<IndexableField> fields = amount.createFields(currencyValue);
|
||||
assertEquals(fields.size(), 3);
|
||||
|
@ -112,41 +137,47 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
assertEquals(schema.getFieldTypeByName("string").toExternal(fields.get(2)), "1.50,EUR");
|
||||
|
||||
// A few tests on the provider directly
|
||||
ExchangeRateProvider p = ((CurrencyField) tmp).getProvider();
|
||||
ExchangeRateProvider p = ((CurrencyFieldType)tmp).getProvider();
|
||||
Set<String> availableCurrencies = p.listAvailableCurrencies();
|
||||
assertEquals(5, availableCurrencies.size());
|
||||
assert(p.reload() == true);
|
||||
assert(p.getExchangeRate("USD", "EUR") == 2.5);
|
||||
assertTrue(p.reload());
|
||||
assertEquals(2.5, p.getExchangeRate("USD", "EUR"), 0.00000000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMockExchangeRateProvider() throws Exception {
|
||||
assumeTrue("This test is only applicable to the mock exchange rate provider",
|
||||
expectedProviderClass.equals(MockExchangeRateProvider.class));
|
||||
|
||||
SolrCore core = h.getCore();
|
||||
IndexSchema schema = core.getLatestSchema();
|
||||
SchemaField amount = schema.getField("mock_amount");
|
||||
SchemaField field = schema.getField(fieldName);
|
||||
FieldType fieldType = field.getType();
|
||||
ExchangeRateProvider provider = ((CurrencyFieldType)fieldType).getProvider();
|
||||
|
||||
// A few tests on the provider directly
|
||||
ExchangeRateProvider p = ((CurrencyField)amount.getType()).getProvider();
|
||||
Set<String> availableCurrencies = p.listAvailableCurrencies();
|
||||
assert(availableCurrencies.size() == 3);
|
||||
assert(p.reload() == true);
|
||||
assert(p.getExchangeRate("USD", "EUR") == 0.8);
|
||||
assertEquals(3, provider.listAvailableCurrencies().size());
|
||||
assertTrue(provider.reload());
|
||||
assertEquals(0.8, provider.getExchangeRate("USD", "EUR"), 0.00000000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrencyRangeSearch() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
final int emptyDocs = atLeast(50); // times 2
|
||||
final int negDocs = atLeast(5);
|
||||
|
||||
assertU(adoc("id", "0", field(), "0,USD")); // 0
|
||||
assertU(adoc("id", "0", fieldName, "0,USD")); // 0
|
||||
// lots of docs w/o values
|
||||
for (int i = 100; i <= 100 + emptyDocs; i++) {
|
||||
assertU(adoc("id", "" + i));
|
||||
}
|
||||
// docs with values in ranges we'll query
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
assertU(adoc("id", "" + i, field(), i + ",USD"));
|
||||
assertU(adoc("id", "" + i, fieldName, i + ",USD"));
|
||||
}
|
||||
// more docs w/o values
|
||||
for (int i = 500; i <= 500 + emptyDocs; i++) {
|
||||
|
@ -154,62 +185,62 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
}
|
||||
// some negative values
|
||||
for (int i = -100; i > -100 - negDocs; i--) {
|
||||
assertU(adoc("id", "" + i, field(), i + ",USD"));
|
||||
assertU(adoc("id", "" + i, fieldName, i + ",USD"));
|
||||
}
|
||||
assertU(adoc("id", "40", field(), "0,USD")); // 0
|
||||
assertU(adoc("id", "40", fieldName, "0,USD")); // 0
|
||||
|
||||
assertU(commit());
|
||||
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[2.00,USD TO 5.00,USD]"),
|
||||
fieldName+":[2.00,USD TO 5.00,USD]"),
|
||||
"//*[@numFound='4']");
|
||||
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[0.50,USD TO 1.00,USD]"),
|
||||
fieldName+":[0.50,USD TO 1.00,USD]"),
|
||||
"//*[@numFound='1']");
|
||||
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[24.00,USD TO 25.00,USD]"),
|
||||
fieldName+":[24.00,USD TO 25.00,USD]"),
|
||||
"//*[@numFound='0']");
|
||||
|
||||
// "GBP" currency code is 1/2 of a USD dollar, for testing.
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[0.50,GBP TO 1.00,GBP]"),
|
||||
fieldName+":[0.50,GBP TO 1.00,GBP]"),
|
||||
"//*[@numFound='2']");
|
||||
|
||||
// "EUR" currency code is 2.5X of a USD dollar, for testing.
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[24.00,EUR TO 25.00,EUR]"),
|
||||
fieldName+":[24.00,EUR TO 25.00,EUR]"),
|
||||
"//*[@numFound='1']");
|
||||
|
||||
// Slight asymmetric rate should work.
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[24.99,EUR TO 25.01,EUR]"),
|
||||
fieldName+":[24.99,EUR TO 25.01,EUR]"),
|
||||
"//*[@numFound='1']");
|
||||
|
||||
// Open ended ranges without currency
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[* TO *]"),
|
||||
fieldName+":[* TO *]"),
|
||||
"//*[@numFound='" + (2 + 10 + negDocs) + "']");
|
||||
|
||||
// Open ended ranges with currency
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[*,EUR TO *,EUR]"),
|
||||
fieldName+":[*,EUR TO *,EUR]"),
|
||||
"//*[@numFound='" + (2 + 10 + negDocs) + "']");
|
||||
|
||||
// Open ended start range without currency
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[* TO 5,USD]"),
|
||||
fieldName+":[* TO 5,USD]"),
|
||||
"//*[@numFound='" + (2 + 5 + negDocs) + "']");
|
||||
|
||||
// Open ended start range with currency (currency for the * won't matter)
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[*,USD TO 5,USD]"),
|
||||
fieldName+":[*,USD TO 5,USD]"),
|
||||
"//*[@numFound='" + (2 + 5 + negDocs) + "']");
|
||||
|
||||
// Open ended end range
|
||||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[3 TO *]"),
|
||||
fieldName+":[3 TO *]"),
|
||||
"//*[@numFound='8']");
|
||||
}
|
||||
|
||||
|
@ -220,23 +251,26 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
// bogus currency
|
||||
assertQEx("Expected exception for invalid currency",
|
||||
req("fl", "*,score", "q",
|
||||
field()+":[3,HOSS TO *]"),
|
||||
fieldName+":[3,HOSS TO *]"),
|
||||
400);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrencyPointQuery() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
assertU(adoc("id", "" + 1, field(), "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, field(), "15.00,MXN"));
|
||||
assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, fieldName, "15.00,MXN"));
|
||||
assertU(commit());
|
||||
assertQ(req("fl", "*,score", "q", field()+":10.00,USD"), "//str[@name='id']='1'");
|
||||
assertQ(req("fl", "*,score", "q", field()+":9.99,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", field()+":10.01,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", field()+":15.00,MXN"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.50,USD"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.49,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.51,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":10.00,USD"), "//str[@name='id']='1'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":9.99,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":10.01,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":15.00,MXN"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.50,USD"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.49,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.51,USD"), "//*[@numFound='0']");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
|
@ -247,7 +281,7 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
int initDocs = 200000;
|
||||
|
||||
for (int i = 1; i <= initDocs; i++) {
|
||||
assertU(adoc("id", "" + i, field(), (r.nextInt(10) + 1.00) + ",USD"));
|
||||
assertU(adoc("id", "" + i, fieldName, (r.nextInt(10) + 1.00) + ",USD"));
|
||||
if (i % 1000 == 0)
|
||||
System.out.println(i);
|
||||
}
|
||||
|
@ -255,15 +289,15 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
assertU(commit());
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lower = r.nextInt(10) + 1.00;
|
||||
assertQ(req("fl", "*,score", "q", field()+":[" + lower + ",USD TO " + (lower + 10.00) + ",USD]"), "//*");
|
||||
assertQ(req("fl", "*,score", "q", field()+":[" + lower + ",EUR TO " + (lower + 10.00) + ",EUR]"), "//*");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":[" + lower + ",USD TO " + (lower + 10.00) + ",USD]"), "//*");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":[" + lower + ",EUR TO " + (lower + 10.00) + ",EUR]"), "//*");
|
||||
}
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
final RTimer timer = new RTimer();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lower = r.nextInt(10) + 1.00;
|
||||
assertQ(req("fl", "*,score", "q", field()+":[" + lower + ",USD TO " + (lower + (9.99 - (j * 0.01))) + ",USD]"), "//*");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":[" + lower + ",USD TO " + (lower + (9.99 - (j * 0.01))) + ",USD]"), "//*");
|
||||
}
|
||||
|
||||
System.out.println(timer.getTime());
|
||||
|
@ -275,7 +309,7 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
final RTimer timer = new RTimer();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lower = r.nextInt(10) + 1.00;
|
||||
assertQ(req("fl", "*,score", "q", field()+":[" + lower + ",EUR TO " + (lower + (9.99 - (j * 0.01))) + ",EUR]"), "//*");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":[" + lower + ",EUR TO " + (lower + (9.99 - (j * 0.01))) + ",EUR]"), "//*");
|
||||
}
|
||||
|
||||
System.out.println(timer.getTime());
|
||||
|
@ -284,27 +318,42 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
|
||||
@Test
|
||||
public void testCurrencySort() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
|
||||
assertU(adoc("id", "" + 1, field(), "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, field(), "15.00,EUR"));
|
||||
assertU(adoc("id", "" + 3, field(), "7.00,EUR"));
|
||||
assertU(adoc("id", "" + 4, field(), "6.00,GBP"));
|
||||
assertU(adoc("id", "" + 5, field(), "2.00,GBP"));
|
||||
assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, fieldName, "15.00,EUR"));
|
||||
assertU(adoc("id", "" + 3, fieldName, "7.00,EUR"));
|
||||
assertU(adoc("id", "" + 4, fieldName, "6.00,GBP"));
|
||||
assertU(adoc("id", "" + 5, fieldName, "2.00,GBP"));
|
||||
assertU(commit());
|
||||
|
||||
assertQ(req("fl", "*,score", "q", "*:*", "sort", field()+" desc", "limit", "1"), "//str[@name='id']='4'");
|
||||
assertQ(req("fl", "*,score", "q", "*:*", "sort", field()+" asc", "limit", "1"), "//str[@name='id']='3'");
|
||||
assertQ(req("fl", "*,score", "q", "*:*", "sort", fieldName+" desc", "limit", "1"), "//str[@name='id']='4'");
|
||||
assertQ(req("fl", "*,score", "q", "*:*", "sort", fieldName+" asc", "limit", "1"), "//str[@name='id']='3'");
|
||||
}
|
||||
|
||||
public void testExpectedProvider() {
|
||||
SolrCore core = h.getCore();
|
||||
IndexSchema schema = core.getLatestSchema();
|
||||
SchemaField field = schema.getField(fieldName);
|
||||
FieldType fieldType = field.getType();
|
||||
ExchangeRateProvider provider = ((CurrencyFieldType)fieldType).getProvider();
|
||||
assertEquals(expectedProviderClass, provider.getClass());
|
||||
}
|
||||
|
||||
public void testFunctionUsage() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
// "GBP" currency code is 1/2 of a USD dollar, for testing.
|
||||
assertU(adoc("id", "" + i, field(), (((float)i)/2) + ",GBP"));
|
||||
assertU(adoc("id", "" + i, fieldName, (((float)i)/2) + ",GBP"));
|
||||
}
|
||||
for (int i = 9; i <= 11; i++) {
|
||||
assertU(adoc("id", "" + i, field(), i + ",USD"));
|
||||
assertU(adoc("id", "" + i, fieldName, i + ",USD"));
|
||||
}
|
||||
|
||||
assertU(commit());
|
||||
|
@ -312,17 +361,17 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
// direct value source usage, gets "raw" form od default currency
|
||||
// default==USD, so raw==penies
|
||||
assertQ(req("fl", "id,func:field($f)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:5"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=500]");
|
||||
assertQ(req("fl", "id,func:field($f)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:10"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=1000]");
|
||||
assertQ(req("fl", "id,score,"+field(),
|
||||
"q", "{!frange u=500}"+field())
|
||||
assertQ(req("fl", "id,score,"+fieldName,
|
||||
"q", "{!frange u=500}"+fieldName)
|
||||
,"//*[@numFound='5']"
|
||||
,"//str[@name='id']='1'"
|
||||
,"//str[@name='id']='2'"
|
||||
|
@ -330,8 +379,8 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
,"//str[@name='id']='4'"
|
||||
,"//str[@name='id']='5'"
|
||||
);
|
||||
assertQ(req("fl", "id,score,"+field(),
|
||||
"q", "{!frange l=500 u=1000}"+field())
|
||||
assertQ(req("fl", "id,score,"+fieldName,
|
||||
"q", "{!frange l=500 u=1000}"+fieldName)
|
||||
,"//*[@numFound='6']"
|
||||
,"//str[@name='id']='5'"
|
||||
,"//str[@name='id']='6'"
|
||||
|
@ -343,17 +392,17 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
|
||||
// use the currency function to convert to default (USD)
|
||||
assertQ(req("fl", "id,func:currency($f)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:10"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=10]");
|
||||
assertQ(req("fl", "id,func:currency($f)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:5"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=5]");
|
||||
assertQ(req("fl", "id,score"+field(),
|
||||
"f", field(),
|
||||
assertQ(req("fl", "id,score"+fieldName,
|
||||
"f", fieldName,
|
||||
"q", "{!frange u=5}currency($f)")
|
||||
,"//*[@numFound='5']"
|
||||
,"//str[@name='id']='1'"
|
||||
|
@ -362,8 +411,8 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
,"//str[@name='id']='4'"
|
||||
,"//str[@name='id']='5'"
|
||||
);
|
||||
assertQ(req("fl", "id,score"+field(),
|
||||
"f", field(),
|
||||
assertQ(req("fl", "id,score"+fieldName,
|
||||
"f", fieldName,
|
||||
"q", "{!frange l=5 u=10}currency($f)")
|
||||
,"//*[@numFound='6']"
|
||||
,"//str[@name='id']='5'"
|
||||
|
@ -376,17 +425,17 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
|
||||
// use the currency function to convert to MXN
|
||||
assertQ(req("fl", "id,func:currency($f,MXN)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:5"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=10]");
|
||||
assertQ(req("fl", "id,func:currency($f,MXN)",
|
||||
"f", field(),
|
||||
"f", fieldName,
|
||||
"q", "id:10"),
|
||||
"//*[@numFound='1']",
|
||||
"//doc/float[@name='func' and .=20]");
|
||||
assertQ(req("fl", "*,score,"+field(),
|
||||
"f", field(),
|
||||
assertQ(req("fl", "*,score,"+fieldName,
|
||||
"f", fieldName,
|
||||
"q", "{!frange u=10}currency($f,MXN)")
|
||||
,"//*[@numFound='5']"
|
||||
,"//str[@name='id']='1'"
|
||||
|
@ -395,8 +444,8 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
,"//str[@name='id']='4'"
|
||||
,"//str[@name='id']='5'"
|
||||
);
|
||||
assertQ(req("fl", "*,score,"+field(),
|
||||
"f", field(),
|
||||
assertQ(req("fl", "*,score,"+fieldName,
|
||||
"f", fieldName,
|
||||
"q", "{!frange l=10 u=20}currency($f,MXN)")
|
||||
,"//*[@numFound='6']"
|
||||
,"//str[@name='id']='5'"
|
||||
|
@ -411,16 +460,35 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
|
||||
@Test
|
||||
public void testMockFieldType() throws Exception {
|
||||
assumeTrue("This test is only applicable to the mock exchange rate provider",
|
||||
expectedProviderClass.equals(MockExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
|
||||
assertU(adoc("id", "1", "mock_amount", "1.00,USD"));
|
||||
assertU(adoc("id", "2", "mock_amount", "1.00,EUR"));
|
||||
assertU(adoc("id", "3", "mock_amount", "1.00,NOK"));
|
||||
assertU(adoc("id", "1", fieldName, "1.00,USD"));
|
||||
assertU(adoc("id", "2", fieldName, "1.00,EUR"));
|
||||
assertU(adoc("id", "3", fieldName, "1.00,NOK"));
|
||||
assertU(commit());
|
||||
|
||||
assertQ(req("fl", "*,score", "q", "mock_amount:5.0,NOK"), "//*[@numFound='1']", "//str[@name='id']='1'");
|
||||
assertQ(req("fl", "*,score", "q", "mock_amount:1.2,USD"), "//*[@numFound='1']", "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", "mock_amount:0.2,USD"), "//*[@numFound='1']", "//str[@name='id']='3'");
|
||||
assertQ(req("fl", "*,score", "q", "mock_amount:99,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":5.0,NOK"), "//*[@numFound='1']", "//str[@name='id']='1'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":1.2,USD"), "//*[@numFound='1']", "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":0.2,USD"), "//*[@numFound='1']", "//str[@name='id']='3'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":99,USD"), "//*[@numFound='0']");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsymmetricPointQuery() throws Exception {
|
||||
assumeTrue("This test is only applicable to the XML file based exchange rate provider",
|
||||
expectedProviderClass.equals(FileExchangeRateProvider.class));
|
||||
|
||||
clearIndex();
|
||||
assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, fieldName, "15.00,EUR"));
|
||||
assertU(commit());
|
||||
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":15.00,EUR"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.50,USD"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.49,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", fieldName+":7.51,USD"), "//*[@numFound='0']");
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.solr.schema;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests currency field type using FileExchangeRateProvider
|
||||
*/
|
||||
public class CurrencyFieldXmlFileTest extends AbstractCurrencyFieldTest {
|
||||
|
||||
public String field() {
|
||||
return "amount";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsymetricPointQuery() throws Exception {
|
||||
clearIndex();
|
||||
assertU(adoc("id", "" + 1, field(), "10.00,USD"));
|
||||
assertU(adoc("id", "" + 2, field(), "15.00,EUR"));
|
||||
assertU(commit());
|
||||
|
||||
assertQ(req("fl", "*,score", "q", field()+":15.00,EUR"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.50,USD"), "//str[@name='id']='2'");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.49,USD"), "//*[@numFound='0']");
|
||||
assertQ(req("fl", "*,score", "q", field()+":7.51,USD"), "//*[@numFound='0']");
|
||||
}
|
||||
|
||||
}
|
|
@ -40,7 +40,7 @@ public class OpenExchangeRatesOrgProviderTest extends SolrTestCaseJ4 {
|
|||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
AbstractCurrencyFieldTest.assumeCurrencySupport
|
||||
CurrencyFieldTypeTest.assumeCurrencySupport
|
||||
("USD", "EUR", "MXN", "GBP", "JPY");
|
||||
|
||||
super.setUp();
|
||||
|
|
|
@ -202,8 +202,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
||||
|
@ -703,17 +705,22 @@
|
|||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -138,8 +138,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
||||
|
@ -623,17 +625,22 @@
|
|||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- Example exchange rates file for CurrencyField type named "currency" in example schema -->
|
||||
<!-- Example exchange rates file for CurrencyFieldType named "currency" in example schema -->
|
||||
|
||||
<currencyConfig version="1.0">
|
||||
<rates>
|
||||
|
|
|
@ -202,8 +202,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
||||
|
@ -703,17 +705,22 @@
|
|||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<fieldType name="binary" class="solr.BinaryField"/>
|
||||
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
|
||||
<fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/>
|
||||
<fieldType name="currency" class="solr.CurrencyField" currencyConfig="currency.xml" defaultCurrency="USD" precisionStep="8"/>
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
<fieldType name="date" class="solr.TrieDateField" positionIncrementGap="0" precisionStep="0"/>
|
||||
<fieldType name="dates" class="solr.TrieDateField" positionIncrementGap="0" multiValued="true" precisionStep="0"/>
|
||||
<fieldType name="descendent_path" class="solr.TextField">
|
||||
|
@ -504,6 +504,8 @@
|
|||
<dynamicField name="*_tdts" type="tdates" indexed="true" stored="true"/>
|
||||
<dynamicField name="attr_*" type="text_general" multiValued="true" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_pdts" type="pdates" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_dts" type="date" multiValued="true" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_tis" type="tints" indexed="true" stored="true"/>
|
||||
|
|
|
@ -136,8 +136,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="ints" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="strings" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="longs" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true"/>
|
||||
|
@ -601,19 +603,24 @@
|
|||
<fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
|
||||
geo="true" distErrPct="0.025" maxDistErr="0.001" distanceUnits="kilometers" />
|
||||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- Example exchange rates file for CurrencyField type named "currency" in example schema -->
|
||||
<!-- Example exchange rates file for CurrencyFieldType named "currency" in example schema -->
|
||||
|
||||
<currencyConfig version="1.0">
|
||||
<rates>
|
||||
|
|
|
@ -136,8 +136,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="ints" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="strings" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="longs" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true"/>
|
||||
|
@ -625,19 +627,24 @@
|
|||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -199,8 +199,10 @@
|
|||
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
|
||||
<dynamicField name="*_s_ns" type="string" indexed="true" stored="false" />
|
||||
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_l_ns" type="long" indexed="true" stored="false"/>
|
||||
<dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true"/>
|
||||
<dynamicField name="*_t" type="text_general" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true"/>
|
||||
|
@ -760,17 +762,22 @@
|
|||
|
||||
<!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
|
||||
Parameters:
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
precisionStep: Specifies the precisionStep for the TrieLong field used for the amount
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field.
|
||||
The dynamic field must have a field type that extends LongValueFieldType.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
codeStrSuffix: Required. Refers to a dynamic field for the currency code sub-field.
|
||||
The dynamic field must have a field type that extends StrField.
|
||||
Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
|
||||
defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
|
||||
providerClass: Lets you plug in other exchange provider backend:
|
||||
solr.FileExchangeRateProvider is the default and takes one parameter:
|
||||
currencyConfig: name of an xml file holding exchange rates
|
||||
solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
|
||||
ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
|
||||
refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
|
||||
-->
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
|
||||
|
||||
<!-- some examples for different languages (generally ordered by ISO code) -->
|
||||
|
|
|
@ -28,7 +28,8 @@ The following table lists the field types that are available in Solr. The `org.a
|
|||
|BinaryField |Binary data.
|
||||
|BoolField |Contains either true or false. Values of "1", "t", or "T" in the first character are interpreted as true. Any other values in the first character are interpreted as false.
|
||||
|CollationField |Supports Unicode collation for sorting and range queries. ICUCollationField is a better choice if you can use ICU4J. See the section <<language-analysis.adoc#LanguageAnalysis-UnicodeCollation,Unicode Collation>>.
|
||||
|CurrencyField |Supports currencies and exchange rates. See the section <<working-with-currencies-and-exchange-rates.adoc#working-with-currencies-and-exchange-rates,Working with Currencies and Exchange Rates>>.
|
||||
|CurrencyField |Deprecated in favor of CurrencyFieldType.
|
||||
|CurrencyFieldType |Supports currencies and exchange rates. See the section <<working-with-currencies-and-exchange-rates.adoc#working-with-currencies-and-exchange-rates,Working with Currencies and Exchange Rates>>.
|
||||
|DateRangeField |Supports indexing date ranges, to include point in time date instances as well (single-millisecond durations). See the section <<working-with-dates.adoc#working-with-dates,Working with Dates>> for more detail on using this field type. Consider using this field type even if it's just for date instances, particularly when the queries typically fall on UTC year/month/day/hour, etc., boundaries.
|
||||
|ExternalFileField |Pulls values from a file on disk. See the section <<working-with-external-files-and-processes.adoc#working-with-external-files-and-processes,Working with External Files and Processes>>.
|
||||
|EnumField |Allows defining an enumerated set of values which may not be easily sorted by either alphabetic or numeric order (such as a list of severities, for example). This field type takes a configuration file, which lists the proper order of the field values. See the section <<working-with-enum-fields.adoc#working-with-enum-fields,Working with Enum Fields>> for more information.
|
||||
|
|
|
@ -59,7 +59,7 @@ The core functionality of atomically updating a document requires that all field
|
|||
|
||||
If `<copyField/>` destinations are configured as stored, then Solr will attempt to index both the current value of the field as well as an additional copy from any source fields. If such fields contain some information that comes from the indexing program and some information that comes from copyField, then the information which originally came from the indexing program will be lost when an atomic update is made.
|
||||
|
||||
There are other kinds of derived fields that must also be set so they aren't stored. Some spatial field types use derived fields. Examples of this are solr.BBoxField and solr.LatLonType. These types create additional fields which are normally specified by a dynamic field definition. That dynamic field definition must be not stored, or indexing will fail.
|
||||
There are other kinds of derived fields that must also be set so they aren't stored. Some spatial field types use derived fields. Examples of this are solr.BBoxField and solr.LatLonType. CurrencyFieldType also uses derived fields. These types create additional fields which are normally specified by a dynamic field definition. That dynamic field definition must be not stored, or indexing will fail.
|
||||
|
||||
[[UpdatingPartsofDocuments-Example]]
|
||||
=== Example
|
||||
|
|
|
@ -30,11 +30,18 @@ The `currency` FieldType provides support for monetary values to Solr/Lucene wit
|
|||
[[WorkingwithCurrenciesandExchangeRates-ConfiguringCurrencies]]
|
||||
== Configuring Currencies
|
||||
|
||||
The `currency` field type is defined in `schema.xml`. This is the default configuration of this type:
|
||||
.CurrencyField has been Deprecated
|
||||
[WARNING]
|
||||
====
|
||||
CurrencyField has been deprecated in favor of CurrencyFieldType; all configuration examples below use CurrencyFieldType.
|
||||
====
|
||||
|
||||
The `currency` field type is defined in `schema.xml`. This is the default configuration of this type.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8"
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType"
|
||||
amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
----
|
||||
|
||||
|
@ -53,6 +60,26 @@ At indexing time, money fields can be indexed in a native currency. For example,
|
|||
|
||||
During query processing, range and point queries are both supported.
|
||||
|
||||
[[WorkingwithCurrenciesandExchangeRates-Sub-fieldSuffixes]]
|
||||
=== Sub-field Suffixes
|
||||
|
||||
You must specify parameters `amountLongSuffix` and `codeStrSuffix`, corresponding to dynamic fields to be used for the raw amount and the currency dynamic sub-fields, e.g.:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType"
|
||||
amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
defaultCurrency="USD" currencyConfig="currency.xml" />
|
||||
----
|
||||
|
||||
In the above example, the raw amount field will use the `"*_l_ns"` dynamic field, which must exist in the schema and use a long field type, i.e. one that extends `LongValueFieldType`. The currency code field will use the `"*_s_ns"` dynamic field, which must exist in the schema and use a string field type, i.e. one that is or extends `StrField`.
|
||||
|
||||
.Atomic Updates won't work if dynamic sub-fields are stored
|
||||
[NOTE]
|
||||
====
|
||||
As noted on <<updating-parts-of-documents.adoc#UpdatingPartsofDocuments-FieldStorage,Updating Parts of Documents>>, stored dynamic sub-fields will cause indexing to fail when you use Atomic Updates. To avoid this problem, specify `stored="false"` on those dynamic fields.
|
||||
====
|
||||
|
||||
[[WorkingwithCurrenciesandExchangeRates-ExchangeRates]]
|
||||
== Exchange Rates
|
||||
|
||||
|
@ -95,7 +122,8 @@ In this case, you need to specify the `providerClass` in the definitions for the
|
|||
|
||||
[source,xml]
|
||||
----
|
||||
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8"
|
||||
<fieldType name="currency" class="solr.CurrencyFieldType"
|
||||
amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
|
||||
providerClass="solr.OpenExchangeRatesOrgProvider"
|
||||
refreshInterval="60"
|
||||
ratesFileLocation="http://www.openexchangerates.org/api/latest.json?app_id=yourPersonalAppIdKey"/>
|
||||
|
|
Loading…
Reference in New Issue