Php Zend Search Lucene未返回预期结果

Php Zend Search Lucene未返回预期结果,php,lucene,zend-search-lucene,Php,Lucene,Zend Search Lucene,我使用Zend_Search_Lucene创建了一个简单的索引,用于搜索公司名称列表,因为我希望能够提供比简单的MySQL“如%query%”更智能的搜索。我使用了下面的代码,其中“companyname”是公司名称,“document_id”是每个文档的唯一id(我知道Lucene在内部分配了一个id,但我知道这可能会更改,而我的文档id将是静态的) 但是,当我运行以下代码查找名称中包含“XYZ”变体的所有公司时: $index = Zend_Search_Lucene::open('test

我使用Zend_Search_Lucene创建了一个简单的索引,用于搜索公司名称列表,因为我希望能够提供比简单的MySQL“如%query%”更智能的搜索。我使用了下面的代码,其中“companyname”是公司名称,“document_id”是每个文档的唯一id(我知道Lucene在内部分配了一个id,但我知道这可能会更改,而我的文档id将是静态的)

但是,当我运行以下代码查找名称中包含“XYZ”变体的所有公司时:

$index = Zend_Search_Lucene::open('test-index');
$hits = $index->find('companyname:XYZ');
foreach ($hits as $hit)
{
  print "ID: " . $hit->document_id . "\n";
  print "Score: " . $hit->score . "\n";
  print "Company: " . $hit->companyname . "\n";
}
我最后得出以下结论:

ID: 1
Score: 1
Company: XYZ Holdings
我希望XYZ能够匹配所有文档,因为进行此搜索的目的是查找名称相同但标点符号稍有不同的公司,这在简单的LIKE子句中是无法满足的。Lucene不匹配所有文档有什么原因吗?我能做些什么来解决这个问题吗

如果我搜索“companyname:“x.y.z holdings””,我也会遇到同样的问题——除了“companyname:“x.y.z holdings””之外,这与任何东西都不匹配。我希望Lucene能算出“控股”和“控股”足够接近,可以认为是一对

我相当确定所有文档都已编入索引,因为如果搜索“X.Y.Z”,我会得到文档2和3的匹配项


编辑:忘记提到PHP版本(5.3.5-1ubuntu7.4,带Suhosin补丁)和Zend Framework版本(1.11.10-0ubuntu1)。

您可以通过在索引内容之前对其进行预处理来解决此问题。Lucene将使用代币,您需要将它们视为单独的单位。我在过去做了类似的事情来匹配版本号,这样搜索2.0也会提供2.0.3,例如,而不是1.2.0

这里的toCanonic()函数并不完美。我建议您编写自己的测试套件,并构建一个测试套件,以确保它按照预期转换文本。它所做的是通过将看起来像首字母缩略词的东西分组来构建一个更长的字符串。您也可以在搜索查询中调用它

您需要在companyname\u canonical中搜索,而不是在companyname中搜索

在Zend Lucene中,作为一个过滤器,可能有一种更干净的方法。您可能还希望使用词干分析器来处理复数形式等。已经编写了波特词干分析器的一个实现

当您索引“XYZ Holdings”(假设您使用的是standardAnalyzer)时,将有两个标记“XYZ”和“Holdings”

如果是“X.Y.Z.(控股)有限公司”,则会有“X”、“Y”、“Z”、“控股”和“有限公司”

如果是“X Y Z有限公司”,代币将是“X”、“Y”、“Z”和“有限公司”


当您发出companyname:“X.Y.Z”或companyname:“X Y Z”时,案例2和案例3都匹配。lucene不可能知道案例1中的XYZ也是首字母缩略词


我认为您应该编写自己的标记器,为“XYZ”、“X.Y.Z”和“X Y Z”生成相同的标记,但这可能会干扰其他非首字母缩写的大写词

谢谢,听起来Lucene没有提供我想要的,因为我认为它会为您生成词干,否则我只是在重新发明轮子,我可以保证我会错过一些东西。词干是作为第三方插件提供的。然而,我不认为你所要求的符合正常的词干规则。Java实现有一个更大的生态系统可供选择。“lucene不可能知道案例1中的XYZ也是首字母缩略词”我认为这就是问题所在——我希望lucene知道三个或更多大写字母后跟空格可能是首字母缩略词(如PDF、HTML等)。我真的没有足够的知识来编写我自己的tokeniser。你可以使用StandardAnalyzer(因为它删除了。缩写)。我不知道在zend lucene里有没有类似的东西
ID: 1
Score: 1
Company: XYZ Holdings
function toCanonical($text)
{
    $out = $text . ' ';
    $step = $text;

    $pattern = '/([A-Z])[\s\.-]([A-Z])([^a-z])/';
    while (preg_match($pattern, $step)) {
        $step = preg_replace($pattern, '$1$2$3', $step);
        $out .= $step . ' ';
    }

    return $out;
}

function createDocument($id, $companyName)
{
    $canonicalName = toCanonical($companyName);

    $document = new Zend_Search_Lucene_Document();
    $document->addField(Zend_Search_Lucene_Field::UnIndexed('document_id', $id));
    $document->addField(Zend_Search_Lucene_Field::Text('companyname', $companyName));
    $document->addField(Zend_Search_Lucene_Field::UnStored('companyname_canonical', $canonicalName));

}

$index->addDocument(createDocument(1, 'XYZ Holdings'));
$index->addDocument(createDocument(1, 'X.Y.Z. (Holding) Company'));