记录一次为已创建好的schema添加字段,使用hbase作为数据源。
当迭代不断的向前业务不断的加大,导致前期设计的schema无法满足现在业务的需求,需要在已创建好的schema上新增字段以此来满足需求。
schema新增字段很自然的会想到更新schema,刚好api接口中有个接口void updateSchema(String typeName, SimpleFeatureType featureType) throws IOException,于是在代码中创建一个SimpleFeatureType添加新的字段,调用updateSchema函数修改指定的schema。以为就此大功告成,没想到报错,提示
updating schema columns is not allowed
查看该api接口的源码发现不支持修改已经创建好的schema的字段,源码如下图所示:
提供的api接口不支持修改已创建schema的字段,但是发现在指定的catalog下创建一个schema都会在hbase中该catalog的元数据表中添加如下图所示信息:
上图中可以看到rowkey为*attributes的value记录着schema的元数据,尝试使用hbase shell的put命令修改该value的值进行新增,put命令为:
put ‘test’,“testtypename~attributes”,“m:v”,“myid:String,value:String:index=true,temp:String,dtg:Date,*geom:Point:srid=4326;geomesa.keywords=‘testkeywords’,geomesa.index.dtg=‘dtg’,geomesa.table.sharing=‘false’,geomesa.indices=‘z3:2:3,z2:2:3,id:1:3,attr:5:3’,geomesa.z3.interval=‘week’”
其中temp:String为新增字段,设置成功,并且新增数据也可以成功,但是查询的时候报
ERROR Invalid TWKB geometry type 0 java.lang.IllegalArgumentException:
Invalid TWKB geometry type 0 at
org.locationtech.geomesa.features.serialization.TwkbSerializationclass.deserialize(TwkbSerialization.scala:198atorg.locationtech.geomesa.features.kryo.serialization.KryoGeometrySerializationclass.deserialize(TwkbSerialization.scala:198 at org.locationtech.geomesa.features.kryo.serialization.KryoGeometrySerializationclass.deserialize(TwkbSerialization.scala:198atorg.locationtech.geomesa.features.kryo.serialization.KryoGeometrySerialization.deserialize(KryoGeometrySeriali
at
org.locationtech.geomesa.features.kryo.impl.KryoFeatureDeserializationKaTeX parse error: Can't use function '$' in math mode at position 8: anonfun$̲matchReader$8.a…anonfun$matchReader8.apply(KryoFeatureatorg.locationtech.geomesa.features.kryo.impl.ActiveDeserialization8.apply(KryoFeature at org.locationtech.geomesa.features.kryo.impl.ActiveDeserialization8.apply(KryoFeatureatorg.locationtech.geomesa.features.kryo.impl.ActiveDeserializationclass.readFeature(ActiveDeserialization.scala
at
org.locationtech.geomesa.features.kryo.impl.ActiveDeserializationclass.deserialize(ActiveDeserialization.scalaatorg.locationtech.geomesa.features.kryo.KryoFeatureSerializerclass.deserialize(ActiveDeserialization.scala at org.locationtech.geomesa.features.kryo.KryoFeatureSerializerclass.deserialize(ActiveDeserialization.scalaatorg.locationtech.geomesa.features.kryo.KryoFeatureSerializerMutableActiveSerializer.deserialize(KryoFeatureSer
at
org.locationtech.geomesa.hbase.index.HBaseIndexAdapterKaTeX parse error: Can't use function '$' in math mode at position 8: anonfun$̲org$locationtec…anonfunorgorgorglocationtechgeomesageomesageomesahbaseindexindexindexHBaseIndex
at scala.collection.IteratorKaTeX parse error: Can't use function '$' in math mode at position 5: anon$̲11.next(Iterato…anon2.next(CloseableIterator.scala:36)atorg.locationtech.geomesa.utils.collection.SelfClosingIterator2.next(CloseableIterator.scala:36) at org.locationtech.geomesa.utils.collection.SelfClosingIterator2.next(CloseableIterator.scala:36)atorg.locationtech.geomesa.utils.collection.SelfClosingIterator$anon1.next(CloseableIterator.scala:162)atorg.locationtech.geomesa.utils.collection.CloseableIterator1.next(CloseableIterator.scala:162) at org.locationtech.geomesa.utils.collection.CloseableIterator1.next(CloseableIterator.scala:162)atorg.locationtech.geomesa.utils.collection.CloseableIterator$anon5.next(CloseableIterator.scala:101)atorg.locationtech.geomesa.utils.collection.CloseableIterator5.next(CloseableIterator.scala:101) at org.locationtech.geomesa.utils.collection.CloseableIterator5.next(CloseableIterator.scala:101)atorg.locationtech.geomesa.utils.collection.CloseableIterator$anon5.next(CloseableIterator.scala:101)atorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit5.next(CloseableIterator.scala:101) at org.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit5.next(CloseableIterator.scala:101)atorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAuditanonfunanonfunanonfunnext2.apply(GeoMesaFeatureReadeatorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit2.apply(GeoMesaFeatureReade at org.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit2.apply(GeoMesaFeatureReadeatorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAuditanonfunanonfunanonfunnext2.apply(GeoMesaFeatureReadeatorg.locationtech.geomesa.utils.stats.MethodProfiling2.apply(GeoMesaFeatureReade at org.locationtech.geomesa.utils.stats.MethodProfiling2.apply(GeoMesaFeatureReadeatorg.locationtech.geomesa.utils.stats.MethodProfilingclass.profile(MethodProfiling.scala:19)
at
org.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit.profile(GeoMesaFeatureReader.scala:90)
at
org.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderWithAudit.next(GeoMesaFeatureReader.scala:103)
at
org.locationtech.geomesa.index.geotools.GeoMesaFeatureReaderKaTeX parse error: Can't use function '$' in math mode at position 5: anon$̲2.org$locationt…anon2.next(GeoMesaFeatureReader.scala:65)atorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReader2.next(GeoMesaFeatureReader.scala:65) at org.locationtech.geomesa.index.geotools.GeoMesaFeatureReader2.next(GeoMesaFeatureReader.scala:65)atorg.locationtech.geomesa.index.geotools.GeoMesaFeatureReader$anon2.next(GeoMesaFeatureReader.scala:65)atorg.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:73)atorg.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:43)atorg.geotools.feature.collection.DelegateFeatureIterator.next(DelegateFeatureIterator.java:66)atorg.locationtech.geomesa.utils.collection.CloseableIterator2.next(GeoMesaFeatureReader.scala:65) at org.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:73) at org.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:43) at org.geotools.feature.collection.DelegateFeatureIterator.next(DelegateFeatureIterator.java:66) at org.locationtech.geomesa.utils.collection.CloseableIterator2.next(GeoMesaFeatureReader.scala:65)atorg.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:73)atorg.geotools.feature.FeatureReaderIterator.next(FeatureReaderIterator.java:43)atorg.geotools.feature.collection.DelegateFeatureIterator.next(DelegateFeatureIterator.java:66)atorg.locationtech.geomesa.utils.collection.CloseableIterator$anon4.next(CloseableIterator.scala:51)atorg.locationtech.geomesa.utils.collection.CloseableIterator4.next(CloseableIterator.scala:51) at org.locationtech.geomesa.utils.collection.CloseableIterator4.next(CloseableIterator.scala:51)atorg.locationtech.geomesa.utils.collection.CloseableIterator$anon4.next(CloseableIterator.scala:49)atscala.collection.Iterator4.next(CloseableIterator.scala:49) at scala.collection.Iterator4.next(CloseableIterator.scala:49)atscala.collection.Iteratorclass.foreach(Iterator.scala:742) at
org.locationtech.geomesa.utils.collection.CloseableIteratorKaTeX parse error: Can't use function '$' in math mode at position 5: anon$̲4.foreach(Close…anonfun$export1.apply(ExportCommand.scala:84)atorg.locationtech.geomesa.tools.export.ExportCommand1.apply(ExportCommand.scala:84) at org.locationtech.geomesa.tools.export.ExportCommand1.apply(ExportCommand.scala:84)atorg.locationtech.geomesa.tools.export.ExportCommandanonfunanonfunanonfunexport1.apply(ExportCommand.scala:84)atorg.locationtech.geomesa.utils.io.WithClose1.apply(ExportCommand.scala:84) at org.locationtech.geomesa.utils.io.WithClose1.apply(ExportCommand.scala:84)atorg.locationtech.geomesa.utils.io.WithClose.apply(SafeClose.scala:51)
at
org.locationtech.geomesa.tools.export.ExportCommandclass.export(ExportCommand.scala:84)atorg.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.export(HBaseExportCommand.scala:19)atorg.locationtech.geomesa.tools.export.ExportCommandclass.export(ExportCommand.scala:84) at org.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.export(HBaseExportCommand.scala:19) at org.locationtech.geomesa.tools.export.ExportCommandclass.export(ExportCommand.scala:84)atorg.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.export(HBaseExportCommand.scala:19)atorg.locationtech.geomesa.tools.export.ExportCommandclass.export(ExportCommand.scala:77)
at
org.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.export(HBaseExportCommand.scala:19)
at
org.locationtech.geomesa.tools.export.ExportCommandKaTeX parse error: Can't use function '$' in math mode at position 8: anonfun$̲execute$2anonfun$apply1.apply(ExportCommand.scaatorg.locationtech.geomesa.tools.export.ExportCommand1.apply(ExportCommand.sca at org.locationtech.geomesa.tools.export.ExportCommand1.apply(ExportCommand.scaatorg.locationtech.geomesa.tools.export.ExportCommandanonfunanonfunanonfunexecute222anonfunanonfunanonfunapply1.apply(ExportCommand.scaatorg.locationtech.geomesa.tools.DataStoreCommand1.apply(ExportCommand.sca at org.locationtech.geomesa.tools.DataStoreCommand1.apply(ExportCommand.scaatorg.locationtech.geomesa.tools.DataStoreCommandclass.withDataStore(Command.scala:60)
at
org.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.withDataStore(HBaseExportCommand.scala:19)
at
org.locationtech.geomesa.tools.export.ExportCommandKaTeX parse error: Can't use function '$' in math mode at position 8: anonfun$̲execute$2.apply…anonfun$execute2.apply(ExportCommand.scala:45)atorg.locationtech.geomesa.utils.stats.MethodProfiling2.apply(ExportCommand.scala:45) at org.locationtech.geomesa.utils.stats.MethodProfiling2.apply(ExportCommand.scala:45)atorg.locationtech.geomesa.utils.stats.MethodProfilingclass.profile(MethodProfiling.scala:26)
at
org.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.profile(HBaseExportCommand.scala:19)
at
org.locationtech.geomesa.tools.export.ExportCommandclass.execute(ExportCommand.scala:45)atorg.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.execute(HBaseExportCommand.scala:19)atorg.locationtech.geomesa.tools.Runnerclass.execute(ExportCommand.scala:45) at org.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.execute(HBaseExportCommand.scala:19) at org.locationtech.geomesa.tools.Runnerclass.execute(ExportCommand.scala:45)atorg.locationtech.geomesa.hbase.tools.export.HBaseExportCommand.execute(HBaseExportCommand.scala:19)atorg.locationtech.geomesa.tools.Runnerclass.main(Runner.scala:28)
at
org.locationtech.geomesa.hbase.tools.HBaseRunner$.main(HBaseRunner.scala:21)
at
org.locationtech.geomesa.hbase.tools.HBaseRunner.main(HBaseRunner.scala)
看错误好像是序列化错误,想到是不是因为添加的字段在已存在的字段之间导致查询到的未添加新字段之前的数据无法序列化为已添加新字段的结构中。于是尝试将新增的字段放到最后,重新修改hbase中的元数据表,修改后如下图所示:
其中add:String为新增字段。修改完之后进行插入数据和查询数据都能成功,查询到的数据中未添加新字段前的数据在新字段这一列为空。
至此为已创建的schema新增字段完成,本次是使用hbase作为数据源,其他的数据源应该也可以通过修改元数据的方式进行新增字段。