我在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中的高亮部分。
<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吗?我已经尝试了几个,我在互联网搜索中发现涉及pack
和preg_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
不可能说你最终在哪里做了双编码,但它在你所包含的代码之外的某个地方。您可以使用ngrep
或wireshark
来查看提交给服务器的实际字节编码,如果您仍然怀疑它在离开应用程序后发生的话。