【问题标题】:Lucene: Wildcards are missing from indexLucene:索引中缺少通配符
【发布时间】:2010-03-05 10:12:15
【问题描述】:

我正在构建一个包含特殊名称的搜索索引 - 包含 !和 ?和 & 和 + 和 ... 我必须以不同的方式进行以下搜索:

我和你

我+你

但无论我做什么(在索引之前尝试使用 queryparser 转义,手动转义它,尝试不同的索引器......) - 如果我用 Luke 检查搜索索引,它们不会出现(问号和 @-symbols 和喜欢出现)

背后的逻辑是我正在对实时建议进行部分搜索(并且字段不是那么大)所以我将它分成“m”和“me”和“+”和“y”和“yo " 和 "you" 然后索引它(这样比通配符查询搜索要快得多(而且索引大小不是大问题)。

所以我需要将这个特殊的通配符也插入到索引中。

这是我的代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Lucene.Net.Analysis;
using Lucene.Net.Util;

namespace AnalyzerSpike
{
    public class CustomAnalyzer : Analyzer
    {
        public override TokenStream TokenStream(string fieldName, TextReader reader)
        {
            return new ASCIIFoldingFilter(new LowerCaseFilter(new CustomCharTokenizer(reader)));
        }
    }

    public class CustomCharTokenizer : CharTokenizer
    {
        public CustomCharTokenizer(TextReader input) : base(input)
        {

        }

        public CustomCharTokenizer(AttributeSource source, TextReader input) : base(source, input)
        {
        }

        public CustomCharTokenizer(AttributeFactory factory, TextReader input) : base(factory, input)
        {
        }

        protected override bool IsTokenChar(char c)
        {
            return c != ' ';
        }
    }
}

创建索引的代码:

private void InitIndex(string path, Analyzer analyzer)
{
    var writer = new IndexWriter(path, analyzer, true);

    //some multiline textbox that contains one item per line:
    var all = new List<string>(txtAllAvailable.Text.Replace("\r","").Split('\n'));

    foreach (var item in all)
    {
        writer.AddDocument(GetDocument(item));
    }

    writer.Optimize();
    writer.Close();
}

private static Document GetDocument(string name)
{
    var doc = new Document();

    doc.Add(new Field(
        "name",
        DeNormalizeName(name),
        Field.Store.YES,
        Field.Index.ANALYZED));

    doc.Add(new Field(
                "raw_name",
                name,
                Field.Store.YES,
                Field.Index.NOT_ANALYZED));

    return doc;
}

(代码与版本 1.9.x 中的 Lucene.net 一起使用(编辑:抱歉 - 是 2.9.x)但与 Java 中的 Lucene 兼容)

谢谢

【问题讨论】:

  • 你确定你的意思是 1.9.* 吗?您提到 asciifoldingfilter 听起来像是 2.9 的变体。
  • 我应该补充一点,您所描述的要点听起来不错,所以我怀疑我们在您的分析器中没有看到的代码存在问题。例如,您是从另一个类派生它而不是覆盖您需要的所有方法吗?
  • 对不起 - 你是完全正确的 - 它的 2.9.x 版本 - 谢谢!我更新了我的问题并包含了所有相关代码(非规范化代码只是一种自定义方法,用于添加所有空格以加快搜索速度。

标签: lucene lucene.net wildcard indexer


【解决方案1】:

终于有时间再看一遍。这是我的非规范化方法中的一个愚蠢的错误,它确实过滤掉了单个字符部分(就像一开始一样),因此如果被空格包围,它确实过滤掉了加号:-/

感谢 Moleski 的帮助!

private static string DeNormalizeName(string name)
{
    string answer = string.Empty;

    var wordsOnly = Regex.Replace(name, "[^\\w0-9 ]+", string.Empty);
    var filterText = (name != wordsOnly) ? name + " " + wordsOnly : name;

    foreach (var subName in filterText.Split(' '))
    {
        if (subName.Length >= 1)
        {
            for (var j = 1; j <= subName.Length; j++)
            {
                answer += subName.Substring(0, j) + " ";
            }
        }
    }
    return answer.TrimEnd();
}

【讨论】:

  • 我正在学习如何自己做这件事,你认为你可以为你的非规范化方法发布代码吗?我不清楚那是做什么的。谢谢。
  • 我更新了我的答案——但这不是特定于 Lucene 的代码——它只是针对我的特殊情况(它只是一个尖峰——所以不要指望完美的代码)。如果你想要简单的搜索 - 那么忘记我的非规范化方法。它只是在我的特殊情况下用于加速实时建议,因为通配符搜索对于小词来说非常昂贵 - 我想显示以第一个字母或第二个字母开头的建议。
猜你喜欢
  • 1970-01-01
  • 2011-09-09
  • 2018-04-20
  • 2014-05-05
  • 2014-06-11
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
相关资源
最近更新 更多