经过大量调试后我发现了。
这种行为的原因是 Adobe 在实现 ColdFusion 和 Solr 之间的接口时采取的一个非常……呃……不幸的呃……“设计决策”。
因此,您有一个 Solr 索引文件集合,并且希望有选择地清除磁盘上不再存在的文件。我很确定这就是你所经历的情况。
我们假设:
- 有一个文件叫
/path/to/file
在您的系统上和
- 它在 Solr 集合中建立索引
foo
.
当您发出<cfindex collection="foo" action="delete" key="/path/to/file">
,ColdFusion 向 Solr 发送以下 HTTP 请求:
POST /solr/foo/update?wt=xml&version=2.2 (application/xml; charset=UTF-8)
<delete><id>1247603285</id></delete>
这是一个完全合理的请求,Solr 会很乐意满足。唯一奇怪的是里面的数字<id>
。无论如何,此操作后该文件将从索引中消失。
重新索引该文件并将其从磁盘中删除。现在:
- 不再有一个名为
/path/to/file
在你的系统上,但是
- it is still在 Solr 集合中建立索引
foo
.
让我们也做同样的事<cfindex action="delete">
再次操作。
POST /solr/foo/update?wt=xml&version=2.2 (application/xml; charset=UTF-8)
<delete><id>/path/to/file</id></delete>
啊?身份证上不是应该有号码吗?
事实证明,Adobe 的某个人认为使用数字作为索引文件的唯一 ID 是一个非常聪明的主意,呃,节省空间, 我假设。
However由于某些无法解释的原因,只有当有问题的文件仍然存在时才会发生这种情况。如果它不再存在,ColdFusion 将注意到并传递该路径。
检查该数字表明它适合 32 位有符号整数值。 (我检查过,有很多负值uid
集合领域。)
所以这看起来好像他们使用某种返回 32 位的哈希算法并将其放入 int 中。我首先想到的是 CRC32,但事实并非如此。还,java.util.zip.CRC32
返回一个long
,所以首先就不会有任何负值。
Java 中另一个现成的 32 位哈希是......java.lang.Object.hashCode() http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29.
Bingo.
"/path/to/file".hashCode() // -> 1247603285
所以解决方案是永远不要通过文件的路径删除文件,而总是像这样:
<cfindex collection="foo" action="delete" key="#path.hashCode()#">
对于不再存在的文件,这样做是正确的。
更重要的是:对于仍然存在的文件,这也是正确的——ColdFusion 无论如何都会发送哈希码。
在 Adobe 解决此问题之前,这是一个安全且简单的解决方法。
请注意,文件路径区分大小写,并且必须与索引中存储的路径完全匹配。
A quick
<cfsearch collection="foo" name="foo">
没有任何criteria
将返回所有索引条目,因此检索孤立条目的确切路径并不是一个大问题。
Eric Lippert 解释了对象哈希码以及为什么在应用程序中将它们用于任何“实用”的东西是一个坏主意 http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx这是一篇 .NET 文章,但也适用于 Java。
归结为:Adobe 应该存储实际的path在Solr集合中,留下了他们似乎已经尝试过的Solr的性能优化。
我已备案针对 Adobe 的 ColdFusion 错误数据库。