I use fieldA for the sorting with the primary key and fieldB for the searching.
Running the indexing gives me the following error: DocValuesField “fieldName” appears more than once in this document (only one value is allowed per field.)
I suppose tha the problem is that i have fieldA and fieldB on one property.
I can solve it using includePaths to objectC like: @IndexedEmbedded(includePaths = {“fieldA”, “fieldC”, “fieldD”, etc…})
public class ObjectB {
@IndexedEmbedded(includePaths = {"fieldA", "fieldC", "fieldD", etc...})
private ObjectC c;
}
but so i need to write aroung 150 fields into includePaths and i dont want it because they can change.
… but you’ll have essentially the same problem with fieldC and fieldD: they are sortable, so Hibernate Search likely adds doc-values for those fields as well. Maybe Hibernate Search 5 is smart enough to skip that part, though I’m not sure.
Doc-values are typically used for sorts. The thing is, Hibernate Search 5 only supports doc-values for single-valued fields. And in your case, there are multiple instances of ObjectC per ObjectA, so list.c.fieldA/list.c.fieldC/list.c.fieldD are multi-valued. So Hibernate Search 5 cannot handle docvalues on those fields.
The obvious solution would be to upgrade to Hibenate Search 6, which does support docvalues and sorts on multivalued fields. Hibernate Search 6 also has BigInteger support built-in, so you won’t need your custom bridge.
If you’re stuck on Hibernate Search 5 for some reason, I’m not sure I see a solution for you except includePaths. Maybe, just maybe, you could use the programmatic mapping API to generate the includePaths instead of having to hardcode 150 fields. But I can’t help you write that code.
Hmm… My problem is only on the field “fieldA”. If i remove this, all works fine !
Am i able to do something like this, in order to avoid objectD.a, objectD.b, ObjectD.c, etc ?
public class ObjectC {
@Id
@Field(name = "fieldA", bridge = @FieldBridge(impl = BigIntegerNumericFieldBridge.class))
@Field(name = "fieldB")
private BigInteger id;
@Field
@SortableField
private String fieldC;
@Field
@SortableField
private String fieldD;
@IndexedEmbedded
private ObjectD d; // with n properties
@IndexedEmbedded
private ObjectE e; // with n properties
}
public class ObjectB {
@IndexedEmbedded(includePaths = {"fieldA", "fieldC", "ObjectD", "ObjectE"})
private ObjectC c;
}
I can offer a hack to avoid adding doc values in your bridge when the field is multi-valued, but… it’s really just that: a hack. And it might not perform very well, you’ll have to check. Really, you should just upgrade to Hibernate Search 6.
@Override
public void set(final String name, final Object value, final Document document, final LuceneOptions luceneOptions) {
if (value != null) {
+ boolean documentAlreadyHasOneValue = document.getFields().stream().anyMatch(f -> name.equals(f.name()));
final BigInteger integerValue = (BigInteger) value;
final Long indexedValue = integerValue.multiply(storeFactor).longValue();
luceneOptions.addNumericFieldToDocument(name, indexedValue, document);
- document.add(new NumericDocValuesField(name, indexedValue));
+ if (!documentAlreadyHasOneValue) {
+ document.add(new NumericDocValuesField(name, indexedValue));
+ }
}
}
No, I’m afraid includePaths must be an exhaustive list.
java.lang.IllegalArgumentException: DocValuesField “fieldA” appears more than once in this document (only one value is allowed per field) at org.apache.lucene.index.NumericDocValuesWriter.addValue(NumericDocValuesWriter.java:54)
I will be able to migrate in the next year, so i have to find a trick !