I have a trouble with search by the entities using hibernate search. In my case i need to search:
- by all fields;
- by key-value in json field
This is my entity:
@Entity
@Indexed(index = "test")
@Table(name = "test")
@TypeDef(name = "jsonb", typeClass = Jsonb.class)
public class TestEntity {
@Id
@Column(name = "id")
private UUID Id;
@FullTextField
@Column(name = "name", nullable = false, length = 50)
private String name;
@FullTextField
@Column(name = "desc")
private String desc;
@Column(name = "data")
@Type(type = "jsonb")
@ElementCollection
@PropertyBinding(binder = @PropertyBinderRef(type = JsonPropertyBinderNew.class))
private Map<String, Object> data;
//constructor
//getters
//setters
}
Entity have a column in JSONB format. Using PropertyBinder i save it in elastic:
public class JsonPropertyBinder implements PropertyBinder {
@Override
public void bind(PropertyBindingContext context) {
context.dependencies().useRootOnly();
IndexSchemaElement schemaElement = context.indexSchemaElement();
IndexFieldType<String> amountFieldType = context.typeFactory()
.asString().analyzer("english").toIndexFieldType();
context.bridge(Map.class, new Bridge(
schemaElement.field("data", amountFieldType).toReference()));
}
private static class Bridge implements PropertyBridge<Map> {
private IndexFieldReference<String> data;
public Bridge(IndexFieldReference<String> data) {
this.data = data;
}
@Override
public void write(DocumentElement target, Map bridgedElement, PropertyBridgeWriteContext context) {
Gson gson = new Gson();
target.addValue(data, gson.toJson(bridgedElement));
}
}
In elastic it looks like:
data: {"SomeKey":"SomeKey","StringKey":"Stroka","ObjectKey":"ObjectData"}
desc:Fourth
name: Fourth Test Name
When i try to search by field
List<TestEntity> result = searchSession.search(TestEntity.class)
.where(f -> f.exists().field("data.SomeKey"))
.fetchHits(20);
I got exeption: "org.hibernate.search.util.common.SearchException: HSEARCH400504: Unknown field 'data.SomeKey'"
If i try to use simpleQueryString it works but i coud not use fuzzing:
SearchResult<TestEntity> search = searchSession.search(TestEntity.class)
.where(f -> f.simpleQueryString()
.fields("data")
.matching("ObjectKey + ObjectData")
).fetch(20);
If i try to use Predicate DSL i coud not use boolean operators like "AND using +"
List<TestEntity> hits = searchSession.search( TestEntity.class )
.where( f -> f.match().field( "data" )
.matching( "ObjectKey ObjectData" ).fuzzy())
.fetchHits( 20 );
How coud i search in inner json using key-value?