【问题标题】:Problem with Lucene- search not indexing numeric values?Lucene-search 没有索引数值的问题?
【发布时间】:2009-03-17 16:04:23
【问题描述】:

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

这是索引中的数据:

ts |内容 --------------+----------------- 1236917100 |狗 猫 沙鼠 1236630752 |牛猪山羊 1235680249 |狮子虎熊 非数字 |鲈鱼虾虎鱼

我的问题:对“ts:1236630752”的查询没有返回任何命中。但是,对“ts:nonnumeric”的查询会返回命中。

我将“ts”存储为关键字字段,according to documentation“未标记化,但已编入索引和存储。对非文本字段有用,例如日期或 url。”我尝试将其视为“文本”字段,但行为是相同的,只是当 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

输出

运行查询:猪 获得 1 次命中。 ts='1236630752',内容='牛猪山羊' 运行查询:ts:1236630752 获得 0 次点击。 运行查询:1236630752 获得 0 次点击。 运行查询:ts:pig 获得 0 次点击。 运行查询:内容:猪 获得 1 次命中。 ts='1236630752',内容='牛猪山羊' 运行查询:ts:[1236630700 TO 1236630800] 获得 0 次点击。 运行查询:ts:* 打了4次。 ts='1236917100', 内容='狗猫沙鼠' ts='1236630752',内容='牛猪山羊' ts='1235680249', contents='狮虎熊' ts='非数字',内容='鲈鱼虾虎鱼' 运行查询:非数字 获得 1 次命中。 ts='非数字',内容='鲈鱼虾虎鱼' 运行查询:ts:nonnumeric 获得 1 次命中。 ts='非数字',内容='鲈鱼虾虎鱼' 运行查询:鳟鱼 获得 1 次命中。 ts='非数字',内容='鲈鱼虾虎鱼'

【问题讨论】:

    标签: php zend-framework lucene


    【解决方案1】:

    find() 方法对查询进行标记,使用默认的 Analzer,您的数字将几乎被忽略。如果您想搜索一个数字,您必须 construct the query 或使用包含数值的备用 analyzer..

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

    需要注意的是 查询解析器使用标准 分析器标记单独的部分 请求参数。因此所有的转换 应用于索引文本的是 也适用于查询字符串。

    标准分析器可以转换 小写的查询字符串 不区分大小写,删除停用词, 以及其他转换。

    API 方法不转换或 以任何方式过滤输入项。它是 所以更适合电脑 生成或未标记的字段。

    【讨论】:

    • 请注意,较新版本的 Zend Search Lucene 包含一个字母数字分析器;您只需将其设置为默认值。确保在索引脚本的开头以及运行 $index->​​find() 之前将其包括在内: Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive());
    【解决方案2】:

    我习惯于在 Java 下使用 Lucene,所以我无法判断您的代码是否正确,但似乎该字段正在以一种剥离除 [a-zA-Z] 之外的任何内容的方式进行标记化。

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

    【讨论】:

      【解决方案3】:

      通过使用 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 或网络上找不到任何解决此点问题的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-05
        • 2021-05-27
        • 2012-04-28
        • 2013-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多