我有一个非常奇怪的问题,我基本上试图使用springboot和存储库将对象存储在弹性搜索中,并且由于某些原因,我的对象永远不会被持久化。
使用scala
完成此操作案例类:
@Document(collection = "SPECTRUM")
@org.springframework.data.elasticsearch.annotations.Document(indexName = "spectrum", `type` = "spectrum", shards = 1, replicas = 0, refreshInterval = "-1")
case class Spectrum(
@(Field@field)(`type` = FieldType.Nested)
biologicalCompound: Compound,
@(Field@field)(`type` = FieldType.Nested)
chemicalCompound: Compound,
@(Field@field)(`type` = FieldType.Nested)
predictedCompound: Compound,
@(Indexed@field)
deleted: Boolean,
@(Id@field)
id: String,
lastUpdated: String,
@(Field@field)(`type` = FieldType.Nested)
metaData: Array[MetaData],
score: Score,
spectrum: String,
splash: Splash,
submitter: Submitter,
@(Field@field)(`type` = FieldType.Nested)
tags: Array[Tags],
@(Field@field)(`type` = FieldType.Nested)
authors: Array[Author]
)
}
存储库
@Repository("spectrumElasticRepository")
trait ISpectrumElasticRepositoryCustom extends ElasticsearchRepository[Spectrum, String] with SpectrumElasticRepositoryCustom{
def findByBiologicalCompoundInchiKey(inchiKey: String) : java.util.List[Spectrum]
}
测试代码
getRepository.deleteAll()
assert(getRepository.count() == 0)
s"we should be able to store our data" in {
for (spectrum <- exampleRecords) {
val result = getRepository.save(spectrum)
assert(result.isInstanceOf[Spectrum])
}
assert(getRepository.count() == 58)
val data:Iterable[Spectrum] = getRepository.findAll()
}
一旦测试代码点击此行
val data:Iterable[Spectrum] = getRepository.findAll()
导致以下异常
failed to map source [ {}] to class Spectrum
org.springframework.data.elasticsearch.ElasticsearchException: failed to map source [ {}] to class Spectrum
直接查看弹性搜索服务器
localhost:9200/spectrum/_search
看起来没有数据实际附加到任何报告的点击
{
"_index": "spectrum",
"_type": "spectrum",
"_id": "AVNhcpHjnm4IHnHomcXj",
"_score": 1,
"_source": {}
},
因为来源是空的。
任何想法是什么导致了这个?
答案 0 :(得分:1)
这似乎与scala有关。
确保存储在弹性搜索数据库中的每个属性都用
索引<强> @BeanProperty 强>
喜欢这里
@Document(collection = "SPECTRUM")
@org.springframework.data.elasticsearch.annotations.Document(indexName = "spectrum", `type` = "spectra", shards = 1, replicas = 0, refreshInterval = "-1")
case class Spectrum(
@BeanProperty
@(Field@field)(`type` = FieldType.Nested)
biologicalCompound: Compound,
@BeanProperty
@(Field@field)(`type` = FieldType.Nested)
chemicalCompound: Compound,
@BeanProperty
@(Field@field)(`type` = FieldType.Nested)
predictedCompound: Compound,
@BeanProperty
@(Indexed@field)
deleted: Boolean,
@BeanProperty
@(Id@field)
id: String,
lastUpdated: String,
@BeanProperty
@(Field@field)(`type` = FieldType.Nested)
metaData: Array[MetaData],
@BeanProperty
score: Score,
@BeanProperty
spectrum: String,
@BeanProperty
splash: Splash,
@BeanProperty
submitter: Submitter,
@BeanProperty
@(Field@field)(`type` = FieldType.Nested)
tags: Array[Tags],
@(Field@field)(`type` = FieldType.Nested)
authors: Array[Author]
)
}
它工作正常并且持久存在这个对象。
显然这是如此丑陋,以至于它让你想知道是否有更好的替代方案,或者编写一个scala识别包装器是有意义的。
另外,您可以使用自己选择的方法覆盖utilzied对象映射器和实体impl。这可以在您的配置类中完成。
@Autowired
val objectMapper:ObjectMapper = null
@Bean
def elasticsearchTemplate: ElasticsearchOperations = {
new ElasticsearchTemplate(client,new EntityMapperImpl(objectMapper))
}
@Bean
def client: Client = {
val client = new TransportClient()
val address = new InetSocketTransportAddress(hostname, port)
client.addTransportAddress(address)
client
}
class EntityMapperImpl(val mapper: ObjectMapper) extends EntityMapper {
override def mapToString(`object`: scala.Any): String = mapper.writeValueAsString(`object`)
override def mapToObject[T](source: String, clazz: Class[T]): T = mapper.readValue(source, clazz)
}
对象映射器的确切配置看起来像
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
//required, in case we are provided with a list of value
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.setSerializationInclusion(Include.NON_NULL);
mapper
只需要在某处注册为bean