Java uniqueKey生成在SolrCloud中不起作用(但在独立的情况下起作用)
我遇到了一个奇怪的问题,当同一个应用程序代码在SolrCloud中索引一个没有唯一键(应该由SOLR自动生成)的文档时失败,并在独立的SOLR实例中成功索引它(或者甚至在云模式下,但从其中一个副本的web界面)。很明显,区别只存在于客户端(CloudSolrClient vs HttpSolrClient)和SOLR URL(Zokeeper主机名+端口vs独立SOLR实例主机名和端口)之间 我正在使用Solr5.1。在云模式下,我有1个碎片和3个副本。 : 架构默认值和copyFields不能用于填充uniqueKey字段。您可以使用UUIDUpdateProcessorFactory自动生成uniqueKey值 因此,我已将我的uniqueKey字段添加到架构中:Java uniqueKey生成在SolrCloud中不起作用(但在独立的情况下起作用),java,apache,solr,Java,Apache,Solr,我遇到了一个奇怪的问题,当同一个应用程序代码在SolrCloud中索引一个没有唯一键(应该由SOLR自动生成)的文档时失败,并在独立的SOLR实例中成功索引它(或者甚至在云模式下,但从其中一个副本的web界面)。很明显,区别只存在于客户端(CloudSolrClient vs HttpSolrClient)和SOLR URL(Zokeeper主机名+端口vs独立SOLR实例主机名和端口)之间 我正在使用Solr5.1。在云模式下,我有1个碎片和3个副本。 : 架构默认值和copyFields不能
<fieldType name="uuid" class="solr.UUIDField" indexed="true" />
...
<field name="id" type="uuid" indexed="true" stored="true" required="true" />
...
<uniqueKey>id</uniqueKey>
{
"add": {
"doc": {
.....
},
"boost": 1.0,
"overwrite": true,
"commitWithin": 1000
}
}
如果使用CloudSolrClient,会发生以下情况(通过调试发现):
[http://replica_1_host:port/solr/collection_name/,
http://replica_2_host:port/solr/collection_name/,
http://replica_3_host:port/solr/collection_name/]
LBHttpSolrClient.Req req = new LBHttpSolrClient.Req(request, theUrlList);
LBHttpSolrClient.Rsp rsp = lbClient.request(req);
return rsp.getResponse();
其中第二行出现异常而失败我使用本地代理来查看我的应用程序发送的这两个请求之间的差异,以便了解它们之间的差异。看起来唯一的区别是内容类型。在云模式下,发布文档的有效负载以“application/javabin”的形式发送,而在独立模式下,它以“application/xml;charset=UTF-8”的形式发送。其他一切都一样。第一个请求的结果是400,而第二个请求的结果是200。我认为这可能是一个SolrJ/SOLR错误,因此提交了一份文件。将保持此线程的更新。首先,它在独立模式下工作,因为版本5.1中的HttpSolrClient以XML形式发送负载(不包括空值-这一部分很重要),而CloudSolrClient以二进制序列化格式(包括空值)以“application/javabin”的形式发送负载。在6.2版中,这两个版本都以二进制序列化格式将有效负载发送为“application/javabin”,因此在6.2版中,云模式和独立模式都会出现此问题 问题的真正原因是为了生成UUID,字段必须完全不存在。如果它存在且为空,则跳过UUID生成。这就是错误的原因。所以,如果我们使用SolrInputDocument对文档进行索引,那么这很容易——我们不应该为“id”字段添加值。但是如果我们使用带有“org.apache.solr.client.solrj.beans.Field”注释的POJO呢?我们不能从中排除字段。这就是发挥作用的地方:
<updateRequestProcessorChain name="uuid">
<!-- Using IgnoreFieldUpdateProcessorFactory because of https://issues.apache.org/jira/browse/SOLR-9493:
can't generate UUID for a field coming as NULL, field must be absent. -->
<processor class="solr.IgnoreFieldUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
身份证件
身份证件
将其保存在solrconfig.xml中,并使用“uuid”updateRequestProcessorChain(如上面的问题所示),一切都像一个符咒一样工作(“id”字段在生成uuid之前从文档中删除)。虽然在这种情况下无法添加带有自定义ID的文档,但这是另一个线程的问题。可能是配置没有传播到所有节点吗?那么,当您在云模式下运行时,接收文档的服务器没有定义更新链?另外,在运行时-例如日志/分发/更新步骤。不,我已经检查过了。所有节点的配置都是完美的。另外,我可以看到对同一个节点的请求失败,即第一个副本。如果请求是从web或非云SolrClient发送的,则该节点可以完美地处理该请求。
{
"add": {
"doc": {
.....
},
"boost": 1.0,
"overwrite": true,
"commitWithin": 1000
}
}
[http://replica_1_host:port/solr/collection_name/,
http://replica_2_host:port/solr/collection_name/,
http://replica_3_host:port/solr/collection_name/]
LBHttpSolrClient.Req req = new LBHttpSolrClient.Req(request, theUrlList);
LBHttpSolrClient.Rsp rsp = lbClient.request(req);
return rsp.getResponse();
POST http://replica_1_host:port/solr/collection_name/update?wt=javabin&version=2 HTTP/1.1
POST http://replica_2_host:port/solr/collection_name/update?wt=javabin&version=2 HTTP/1.1
POST http://replica_3_host:port/solr/collection_name/update?wt=javabin&version=2 HTTP/1.1
<updateRequestProcessorChain name="uuid">
<!-- Using IgnoreFieldUpdateProcessorFactory because of https://issues.apache.org/jira/browse/SOLR-9493:
can't generate UUID for a field coming as NULL, field must be absent. -->
<processor class="solr.IgnoreFieldUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>