Solr查询响应包含非utf-8字符


Solr query response contains non-utf-8 characters

我在Fedora 20和Tomcat 7上运行的Solr中索引法语文本。我已经尝试了solr 4.8.1和4.9.0。问题是title_fr字段以某种奇怪的编码从查询返回。

索引和检索是使用内置的curl从PHP完成的。索引请求使用"extract"并传入一些额外的字段——这是PHP curl的POST数组转储。

[literal.id] => cdddd
[uprefix] => attr_
[fmap.content] => text_fr
[literal.title] =>  Québec laisse tomber 
[commit] => true
[myfile] => CURLFile Object ( 
    [name] => /tmp/cccz6GT4n
    [mime] => text/html
    [postname] => cccz6GT4n
)
[literal.url] => /features
[literal.type_s] => content
[literal.extractFormat] => text
[literal.id_s] => chapZrZqYJcEcG
[literal.title_fr] =>  Québec laisse tomber 
[literal.lang_s] => fr

这会生成一个多部分mime的POST到Solr。我已经确认所有部分的编码都是UTF-8。

问题是,当从查询返回结果时,title_fr字段的编码很奇怪。JSON响应字符串为(XML也是如此;请注意,我已经添加了一对回车,使有趣的位可见而不滚动)

{"responseHeader":{"status":0,"QTime":7,"params":{"hl.fragsize":"500","hl.mergeContinuous":"true","fl":"id,score,title,id_s,title_fr,title_en","sort":"","hl.snippets":"500","q":"text_fr:Québec title_fr:Québec","hl.fl":"text_en,text_fr,title_en,title_fr","wt":"json","hl":"true","rows":"10000"}},"response":{"numFound":1,"start":0,"maxScore":0.1354348,"docs":[{"id":"cddd",
"title_fr":[" Québec laisse tomber "],"id_s":"cddd","score":0.1354348}]},
"highlighting":{"cddd":{"text_fr":[" 'n 'n  'n  'n  'n  'n  'n  'n  'n 'n 'n<em>Québec</em>  téléphone'nLe conflit à Gaza plombe  'nà Gaza a"]}}}

第二行显示了title_fr返回的位置—它在我的编辑器中看起来好像是用ISO-8859-1编码的,但是PHP的iconv('iso8859-1', 'utf-8'. ...)只是将有趣的字符加倍。第三行显示了经过合理编码的text_fr中的高亮部分。

schema.xml使用通配符
   <dynamicField name="*_fr"  type="text_fr"    indexed="true"  stored="true" multiValued="true"/>

应该同时覆盖text_fr和title_fr。

我怀疑Solr extract没有将POST中的字符作为UTF-8处理——对于从管理界面发出的查询,这些有趣的字符在所有响应格式中都显示出来。

我已经修复了server.xml中Tomcat的连接器

<Connector port="8080" protocol="HTTP/1.1"
           URIEncoding="UTF-8"
           connectionTimeout="20000"
           redirectPort="8443" />

尽管我被告知Solr不再需要它了。

如果是这种情况,查询将不匹配标题。

如果没有强制提取来正确处理编码,有人知道PHP调用将把title_fr字符串转换回UTF-8吗?我已经尝试了几个,我在互联网搜索中发现涉及packpreg_replace_callback,但似乎没有任何意义的返回字符串。

我怀疑您在将数组提交给Solr之前对其进行了双重编码。您得到的字符串至少是您的字符串编码两次,其中它首先转换为utf-8,然后再次转换为utf-8(这次假设它是iso-8859-1,而它是utf-8)。

所以你的直觉是对的,但是你把编码弄反了。

$ php -r 'print(iconv("utf-8", "iso-8859-1", "Québec laisse tomber"));'
Québec laisse tomber

不可能说你最终在哪里做了双编码,但它在你所包含的代码之外的某个地方。您可以使用ngrepwireshark来查看提交给服务器的实际字节编码,如果您仍然怀疑它在离开应用程序后发生的话。