Este contenido no está disponible en el idioma seleccionado.
14.6. Bridges
@Field
are converted to strings to be indexed. Built-in bridges automatically translates properties for the Lucene-based Query API. The bridges can be customized to gain control over the translation process.
14.6.1. Built-in Bridges
- null
- Per default
null
elements are not indexed. Lucene does not support null elements. However, in some situation it can be useful to insert a custom token representing thenull
value. See Section 14.1.2, “@Field” for more information. - java.lang.String
- Strings are indexed, as are:
short
,Short
integer
,Integer
long
,Long
float
,Float
double
,Double
BigInteger
BigDecimal
Numbers are converted into their string representation. Note that numbers cannot be compared by Lucene, or used in ranged queries out of the box, and must be paddedNote
Using a Range query has disadvantages. An alternative approach is to use a Filter query which will filter the result query to the appropriate range.The Query Module supports using a customStringBridge
. See Section 14.6.2, “Custom Bridges”. - java.util.Date
- Dates are stored as yyyyMMddHHmmssSSS in GMT time (200611072203012 for Nov 7th of 2006 4:03PM and 12ms EST). When using a
TermRangeQuery
, dates are expressed in GMT.@DateBridge
defines the appropriate resolution to store in the index, for example:@DateBridge(resolution=Resolution.DAY)
. The date pattern will then be truncated accordingly.@Indexed public class Meeting { @Field(analyze=Analyze.NO) @DateBridge(resolution=Resolution.MINUTE) private Date date;
The defaultDate
bridge uses Lucene'sDateTools
to convert from and toString
. All dates are expressed in GMT time. Implement a custom date bridge in order to store dates in a fixed time zone. - java.net.URI, java.net.URL
- URI and URL are converted to their string representation
- java.lang.Class
- Class are converted to their fully qualified class name. The thread context classloader is used when the class is rehydrated
14.6.2. Custom Bridges
14.6.2.1. FieldBridge
FieldBridge
. The FieldBridge
interface provides a property value, which can then be mapped in the Lucene Document
. For example, a property can be stored in two different document fields.
Example 14.13. Implementing the FieldBridge Interface
public class DateSplitBridge implements FieldBridge { private final static TimeZone GMT = TimeZone.getTimeZone("GMT"); public void set(String name, Object value, Document document, LuceneOptions luceneOptions) { Date date = (Date) value; Calendar cal = GregorianCalendar.getInstance(GMT); cal.setTime(date); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH) + 1; int day = cal.get(Calendar.DAY_OF_MONTH); // set year luceneOptions.addFieldToDocument( name + ".year", String.valueOf(year), document); // set month and pad it if needed luceneOptions.addFieldToDocument( name + ".month", month < 10 ? "0" : "" + String.valueOf(month), document); // set day and pad it if needed luceneOptions.addFieldToDocument( name + ".day", day < 10 ? "0" : "" + String.valueOf(day), document); } } //property @FieldBridge(impl = DateSplitBridge.class) private Date date;
Lucene Document
. Instead the addition is delegated to the LuceneOptions
helper. The helper will apply the options selected on @Field
, such as Store
or TermVector
, or apply the chosen @Boost
value.
LuceneOptions
is delegated to add fields to the Document
, however the Document
can also be edited directly, ignoring the LuceneOptions
.
Note
LuceneOptions
shields the application from changes in Lucene API
and simplifies the code.
14.6.2.2. StringBridge
org.infinispan.query.bridge.StringBridge
interface to provide the Lucene-based Query API with an implementation of the expected Object
to String
bridge, or StringBridge
. All implementations are used concurrently, and therefore must be thread-safe.
Example 14.14. Custom StringBridge
implementation
/** * Padding Integer bridge. * All numbers will be padded with 0 to match 5 digits * * @author Emmanuel Bernard */ public class PaddedIntegerBridge implements StringBridge { private int PADDING = 5; public String objectToString(Object object) { String rawInteger = ((Integer) object).toString(); if (rawInteger.length() > PADDING) throw new IllegalArgumentException("Try to pad on a number too big"); StringBuilder paddedInteger = new StringBuilder(); for (int padIndex = rawInteger.length() ; padIndex < PADDING ; padIndex++) { paddedInteger.append('0'); } return paddedInteger.append(rawInteger).toString(); } }
@FieldBridge
annotation allows any property or field in the provided example to use the bridge:
@FieldBridge(impl = PaddedIntegerBridge.class) private Integer length;
14.6.2.3. Two-Way Bridge
TwoWayStringBridge
is an extended version of a StringBridge
, which can be used when the bridge implementation is used on an ID property. The Lucene-based Query API reads the string representation of the identifier and uses it to generate an object. The @FieldBridge
annotation is used in the same way.
Example 14.15. Implementing a TwoWayStringBridge for ID Properties
public class PaddedIntegerBridge implements TwoWayStringBridge, ParameterizedBridge { public static String PADDING_PROPERTY = "padding"; private int padding = 5; //default public void setParameterValues(Map parameters) { Object padding = parameters.get(PADDING_PROPERTY); if (padding != null) this.padding = (Integer) padding; } public String objectToString(Object object) { String rawInteger = ((Integer) object).toString(); if (rawInteger.length() > padding) throw new IllegalArgumentException("Try to pad on a number too big"); StringBuilder paddedInteger = new StringBuilder(); for (int padIndex = rawInteger.length(); padIndex < padding; padIndex++) { paddedInteger.append('0'); } return paddedInteger.append(rawInteger).toString(); } public Object stringToObject(String stringValue) { return new Integer(stringValue); } } @FieldBridge(impl = PaddedIntegerBridge.class, params = @Parameter(name = "padding", value = "10")) private Integer id;
Important
14.6.2.4. Parameterized Bridge
ParameterizedBridge
interface passes parameters to the bridge implementation, making it more flexible. The ParameterizedBridge
interface can be implemented by StringBridge
, TwoWayStringBridge
, FieldBridge
implementations. All implementations must be thread-safe.
ParameterizedBridge
interface, with parameters passed through the @FieldBridge
annotation.
Example 14.16. Configure the ParameterizedBridge Interface
public class PaddedIntegerBridge implements StringBridge, ParameterizedBridge { public static String PADDING_PROPERTY = "padding"; private int padding = 5; //default public void setParameterValues(Map <String,String> parameters) { String padding = parameters.get(PADDING_PROPERTY); if (padding != null) this.padding = Integer.parseInt(padding); } public String objectToString(Object object) { String rawInteger = ((Integer) object).toString(); if (rawInteger.length() > padding) throw new IllegalArgumentException("Try to pad on a number too big"); StringBuilder paddedInteger = new StringBuilder(); for (int padIndex = rawInteger.length() ; padIndex < padding ; padIndex++) { paddedInteger.append('0'); } return paddedInteger.append(rawInteger).toString(); } } //property @FieldBridge(impl = PaddedIntegerBridge.class, params = @Parameter(name = "padding", value = "10") ) private Integer length;
14.6.2.5. Type Aware Bridge
AppliedOnTypeAwareBridge
will get the type the bridge is applied on injected. For example:
- the return type of the property for field/getter-level bridges.
- the class type for class-level bridges.
14.6.2.6. ClassBridge
@ClassBridge
annotation. @ClassBridge
can be defined at class level, and supports the termVector
attribute.
FieldBridge
implementation receives the entity instance as the value parameter, rather than a particular property. The particular CatFieldsClassBridge
is applied to the department instance.The FieldBridge
then concatenates both branch and network, and indexes the concatenation.
Example 14.17. Implementing a ClassBridge
@Indexed @ClassBridge(name = "branchnetwork", store = Store.YES, impl = CatFieldsClassBridge.class, params = @Parameter(name = "sepChar", value = "")) public class Department { private int id; private String network; private String branchHead; private String branch; private Integer maxEmployees; } public class CatFieldsClassBridge implements FieldBridge, ParameterizedBridge { private String sepChar; public void setParameterValues(Map parameters) { this.sepChar = (String) parameters.get("sepChar"); } public void set(String name, Object value, Document document, LuceneOptions luceneOptions) { Department dep = (Department) value; String fieldValue1 = dep.getBranch(); if (fieldValue1 == null) { fieldValue1 = ""; } String fieldValue2 = dep.getNetwork(); if (fieldValue2 == null) { fieldValue2 = ""; } String fieldValue = fieldValue1 + sepChar + fieldValue2; Field field = new Field(name, fieldValue, luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector()); field.setBoost(luceneOptions.getBoost()); document.add(field); } }