从mongodb执行数据导入时,Solr会抛出以下错误:
org.apache.solr.common.SolrException: TransactionLog doesn't know how to serialize class org.bson.types.ObjectId; try implementing ObjectResolver?
at org.apache.solr.update.TransactionLog$1.resolve(TransactionLog.java:100)
at org.apache.solr.common.util.JavaBinCodec.writeVal(JavaBinCodec.java:234)
at org.apache.solr.common.util.JavaBinCodec.writeSolrInputDocument(JavaBinCodec.java:589)
at org.apache.solr.update.TransactionLog.write(TransactionLog.java:395)
at org.apache.solr.update.UpdateLog.add(UpdateLog.java:532)
at org.apache.solr.update.UpdateLog.add(UpdateLog.java:516)
at org.apache.solr.update.DirectUpdateHandler2.doNormalUpdate(DirectUpdateHandler2.java:320)
at org.apache.solr.update.DirectUpdateHandler2.addDoc0(DirectUpdateHandler2.java:239)
at org.apache.solr.update.DirectUpdateHandler2.addDoc(DirectUpdateHandler2.java:194)
at org.apache.solr.update.processor.RunUpdateProcessor.processAdd(RunUpdateProcessorFactory.java:67)
at org.apache.solr.update.processor.UpdateRequestProcessor.processAdd(UpdateRequestProcessor.java:55)
at org.apache.solr.update.processor.DistributedUpdateProcessor.doLocalAdd(DistributedUpdateProcessor.java:979)
at org.apache.solr.update.processor.DistributedUpdateProcessor.versionAdd(DistributedUpdateProcessor.java:1192)
at org.apache.solr.update.processor.DistributedUpdateProcessor.processAdd(DistributedUpdateProcessor.java:748)
at org.apache.solr.update.processor.LogUpdateProcessorFactory$LogUpdateProcessor.processAdd(LogUpdateProcessorFactory.java:103)
at org.apache.solr.handler.dataimport.SolrWriter.upload(SolrWriter.java:80)
at org.apache.solr.handler.dataimport.DataImportHandler$1.upload(DataImportHandler.java:254)
at org.apache.solr.handler.dataimport.DocBuilder.buildDocument(DocBuilder.java:526)
at org.apache.solr.handler.dataimport.DocBuilder.buildDocument(DocBuilder.java:414)
at org.apache.solr.handler.dataimport.DocBuilder.doFullDump(DocBuilder.java:329)
at org.apache.solr.handler.dataimport.DocBuilder.execute(DocBuilder.java:232)
at org.apache.solr.handler.dataimport.DataImporter.doFullImport(DataImporter.java:415)
at org.apache.solr.handler.dataimport.DataImporter.runCmd(DataImporter.java:474)
at org.apache.solr.handler.dataimport.DataImporter.lambda$runAsync$0(DataImporter.java:457)
at java.lang.Thread.run(Thread.java:748)
我的Solr版本是6.6.0。可能是错误的原因以及如何解决?
答案 0 :(得分:2)
我在尝试从mongoDB中的多个集合中导入数据时遇到了这个问题。
假设您没有使用mongo-connector,我使用以下内容导入数据。
自返回的' _id'是ObjectId类型,我的解决方案是转换' _id'在将其索引到solr之前进行String,并在查询' _id'时,在运行查询之前将其转换为ObjectId类型。
下载solr mongo导入程序并进行以下更改。
MongoMapperTransformer.java
public class MongoMapperTransformer extends Transformer {
@Override
public Object transformRow(Map<String, Object> row, Context context) {
for (Map<String, String> map : context.getAllEntityFields()) {
String mongoFieldName = map.get(MONGO_FIELD);
String mongoId = map.get(MONGO_ID);
if (mongoFieldName == null)
continue;
String columnFieldName = map.get(DataImporter.COLUMN);
//If the field is ObjectId convert it into String
if (mongoId != null && Boolean.parseBoolean(mongoId)) {
Object srcId = row.get(columnFieldName);
row.put(columnFieldName, srcId.toString());
}
else{
row.put(columnFieldName, row.get(mongoFieldName));
}
}
return row;
}
public static final String MONGO_FIELD = "mongoField";
//To identify the _id field
public static final String MONGO_ID = "objectIdToString";
}
接下来,替换功能
public Iterator <Map<String, Object>> getData(String query){...}
在MongoDataSource.java中使用以下代码:
@Override
public Iterator<Map<String, Object>> getData(String query) {
DBObject queryObject = new BasicDBObject();
/* If querying by _id, since the id is a string now,
* it has to be converted back to type ObjectId() using the
* constructor
*/
if(query.contains("_id")){
@SuppressWarnings("unchecked")
Map<String, String> queryWithId = (Map<String, String>) JSON.parse(query);
String id = queryWithId.get("_id");
queryObject = new BasicDBObject("_id", new ObjectId(id));
}
else{
queryObject = (DBObject) JSON.parse(query);
}
LOG.debug("Executing MongoQuery: " + query.toString());
long start = System.currentTimeMillis();
mongoCursor = this.mongoCollection.find(queryObject);
LOG.trace("Time taken for mongo :"
+ (System.currentTimeMillis() - start));
ResultSetIterator resultSet = new ResultSetIterator(mongoCursor);
return resultSet.getIterator();
}
完成这些更改后,您可以使用ant构建jar。
将jar(solr mongo importer和mongo-java-driver)复制到lib目录中。我将它们复制到$ {solr-install-dir} / contrib / dataimport-handler / lib
中在solr-config.xml中为上述jar添加lib指令:
<lib dir="${solr.install.dir:../../../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />
最后,这是mongo集合和data-config.xml
的示例User collection
{
"_id" : ObjectId("56e9c892e4b0355017b2fa0f"),
"name" : "User1",
"phone" : "123456789"
}
Address collection
{
"_id" : ObjectId("56e9c892e4b0355017b2fa0f"),
"address" : "#666, Maiden street"
}
数据-config.xml中
别忘了提及objectIdToString =&#34; true&#34;对于_id字段,以便MongoMapperTransformer可以对id进行字符串化。
<dataConfig>
<dataSource name="MyMongo"
type="MongoDataSource"
database="test"
/>
<document name="UserDetails">
<!-- if query="" then it imports everything -->
<entity name="users"
processor="MongoEntityProcessor"
query=""
collection="user"
datasource="MyMongo"
transformer="MongoMapperTransformer">
<field column="_id" name="id" mongoField="_id" objectIdToString="true" />
<field column="phone" name="phone" mongoField="phone"/>
<entity name="address"
processor="MongoEntityProcessor"
query="{_id:'${users._id}'}"
collection="address"
datasource="MyMongo"
transformer="MongoMapperTransformer">
<field column="address" name="adress" mongoField="address"/>
</entity>
</entity>
</document>
</dataConfig>
托管架构将id字段作为字符串。 此外,如果您在mongodb中有嵌套对象,则必须使用脚本转换器在solr中对它们进行索引。
希望这有帮助, 祝你好运!
答案 1 :(得分:1)
根据错误消息,
您需要为org.bson.types.ObjectId
类型实现 JavaBinCodec.ObjectResolver ,因此Solr将知道如何序列化此类的实例。
JavaBinCodec.ObjectResolver Documentation
public static interface JavaBinCodec.ObjectResolver允许扩展名 JavaBinCodec支持任意数据类型的序列化。 此接口的实现者编写一个序列化给定的方法 使用现有JavaBinCodec
的对象
编写 JavaBinCodec.ObjectResolver 实现后,应使用 JavaBinCodec
进行注册public class JavaBinCodec extends Object定义节省空间 用于传输数据的序列化/反序列化格式。 JavaBinCodec内置了许多常用类型。这个 包括原始类型(boolean,byte,short,double,int,long, 常见的Java容器/实用程序(日期,地图,集合, Iterator,String,Object [],byte [])和常用的Solr类型 (NamedList,SolrDocument,SolrDocumentList)。以上各种类型 有一对相关的方法,可以读取和写入该类型 流。
本机不支持的类仍然可以 通过提供JavaBinCodec.ObjectResolver进行序列化/反序列化 知道如何使用不受支持的类的对象。这允许 JavaBinCodec用于编组/解组任意内容。
注意 - JavaBinCodec实例不能重复使用多个实例 马歇尔或解散操作。