Lucene-搜索没有索引数值的问题?

时间:2009-03-17 16:04:23

标签: php zend-framework lucene

我在PHP中使用Lucene(使用Zend Framework实现)。我遇到了一个问题,我无法搜索包含数字的字段。

以下是索引中的数据:

      ts      |    contents
--------------+-----------------
  1236917100  | dog cat gerbil
  1236630752  |  cow pig goat
  1235680249  | lion tiger bear
  nonnumeric  | bass goby trout

我的问题:对“ts:1236630752”的查询不会返回任何匹配。但是,对“ts:nonnumeric”的查询会返回匹配。

我将“ts”存储为关键字字段,according to documentation“未标记,但已编入索引并存储。非常适用于非文本字段,例如日期或网址。”我已经尝试将其视为“文本”字段,但行为是相同的,只是当“ts是文本”时,“ts:*”的查询不返回任何内容。

我正在使用Zend Framework 1.7(刚刚在3天前下载)和PHP 5.2.9。这是我的代码:

<?php

//=========================================================
// Initializes Zend Framework (Zend_Loader).
//=========================================================
set_include_path(realpath('../library') . PATH_SEPARATOR . get_include_path());
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();

//=========================================================
// Delete existing index and create a new one
//=========================================================
define('SEARCH_INDEX', 'test_search_index');
if(file_exists(SEARCH_INDEX))
  foreach(scandir(SEARCH_INDEX) as $file)
    if(!is_dir($file))
      unlink(SEARCH_INDEX . "/$file");

$index = Zend_Search_Lucene::create(SEARCH_INDEX);

//=========================================================
// Create this data in index:
//         ts      |    contents
//   --------------+-----------------
//     1236917100  | dog cat gerbil
//     1236630752  |  cow pig goat
//     1235680249  | lion tiger bear
//     nonnumeric  | bass goby trout
//=========================================================

function add_to_index($index, $ts, $contents) {
  $doc = new Zend_Search_Lucene_Document();
  $doc->addField(Zend_Search_Lucene_Field::Keyword('ts', $ts));
  $doc->addField(Zend_Search_Lucene_Field::Text('contents', $contents));
  $index->addDocument($doc);
}

add_to_index($index, '1236917100', 'dog cat gerbil');
add_to_index($index, '1236630752', 'cow pig goat');
add_to_index($index, '1235680249', 'lion tiger bear');
add_to_index($index, 'nonnumeric', 'bass goby trout');

//=========================================================
// Run some test queries and output results
//=========================================================

echo '<html><body><pre>';

function run_query($index, $query) {
  echo "Running query:  $query\n";
  $hits = $index->find($query);
  echo 'Got ' . count($hits) . " hits.\n";
  foreach($hits as $hit)
    echo "  ts='$hit->ts', contents='$hit->contents'\n";
  echo "\n";
}

run_query($index, 'pig');           //1 hit
run_query($index, 'ts:1236630752'); //0 hits
run_query($index, '1236630752');    //0 hits
run_query($index, 'ts:pig');        //0 hits
run_query($index, 'contents:pig');  //1 hits
run_query($index, 'ts:[1236630700 TO 1236630800]'); //0 hits (range query)
run_query($index, 'ts:*');          //4 hits if ts is keyword, 1 hit otherwise
run_query($index, 'nonnumeric');    //1 hits
run_query($index, 'ts:nonnumeric'); //1 hits
run_query($index, 'trout');         //1 hits

输出

Running query:  pig
Got 1 hits.
  ts='1236630752', contents='cow pig goat'

Running query:  ts:1236630752
Got 0 hits.

Running query:  1236630752
Got 0 hits.

Running query:  ts:pig
Got 0 hits.

Running query:  contents:pig
Got 1 hits.
  ts='1236630752', contents='cow pig goat'

Running query:  ts:[1236630700 TO 1236630800]
Got 0 hits.

Running query:  ts:*
Got 4 hits.
  ts='1236917100', contents='dog cat gerbil'
  ts='1236630752', contents='cow pig goat'
  ts='1235680249', contents='lion tiger bear'
  ts='nonnumeric', contents='bass goby trout'

Running query:  nonnumeric
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

Running query:  ts:nonnumeric
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

Running query:  trout
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

3 个答案:

答案 0 :(得分:4)

find()方法将查询标记化,并且使用默认的Analzer,您的数字将被忽略。如果您要搜索某个号码,则必须construct the query或使用包含数值的其他analyzer

http://framework.zend.com/manual/en/zend.search.lucene.searching.html

  

重要的是要注意到   查询解析器使用标准   分析器标记化的各个部分   请求参数。因此所有的转变   适用于索引文本的是   也适用于查询字符串。

     

标准分析仪可以转换   查询字符串为小写的   不区分大小写,删除停用词,   并阻止其他转变。

     

API方法不会转换或   以任何方式过滤输入术语。它的   因此更适合电脑   生成或未标记的字段。

答案 1 :(得分:2)

我习惯在Java下使用Lucene所以我不知道你的代码是否正确,但是看起来这个字段正在以一种剥离任何exept [a-zA-Z]的方式进行组织化。 / p>

使用像http://www.getopt.org/luke/这样的索引浏览器工具来查看索引中的确切内容可能有助于阐明情况。

答案 2 :(得分:0)

我可以通过使用Zend / Search / Lucene / Analysis / Analyzer / Common / TextNum.php作为默认值来轻松获取文本和数字(如上所述使用:: setDefault(...)。

我的问题是我试图用很长的历史记录和许多版本号索引大量的软件和硬件。 Zend Search Lucene没有像“1.5.3”这样的“单词”或带点(IP地址,例如),下划线或连字符的任何东西。

我首先制作了TextNum.php的副本,重命名为TextNumSSC.php(SSC是我们的应用程序名称)并尝试编辑RegEx:

do {
                 if (! preg_match('/[a-zA-Z0-9.-_]+/', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_position)) { 
                     // It covers both cases a) there are no matches (preg_match(...) === 0)
                     // b) error occured (preg_match(...) === FALSE)
                     return null;
                 }

仍然没有运气。

然后我按照指示的方式安装http://codefury.net/projects/StandardAnalyzer/,在Zend目录结构之外,将RegEx更改为

'/[a-zA-Z0-9.-_]+/'

现在可行。

不确定导致此问题的根本原因,但无法在SO或网络上找到解决此问题的任何内容。