Lucene: подстановочные знаки отсутствуют в индексе - PullRequest
2 голосов
/ 05 марта 2010

Я строю поисковый индекс, который содержит специальные имена - содержащие!а также ?и & и + и ... Я должен идти по следующим поискам по-разному:

я и ты

я + ты

Но что бы я ни делал (пробовал с queryparserэкранирование перед индексацией, экранирование вручную, пробование разных индексаторов ...) - если я проверяю индекс поиска с помощью Люка, они не отображаются (отображаются вопросительные знаки и символы @ -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;
}

(Код с Lucene.net в версии 1.9.x (РЕДАКТИРОВАТЬ: извините - было 2.9.x), но совместимо с Lucene из Java)

Thx

1 Ответ

0 голосов
/ 16 марта 2010

Наконец-то появилось время снова посмотреть на это. И это была какая-то глупая ошибка в моем методе денормализации, который отфильтровывал отдельные символьные части (как это было в начале), и, таким образом, он отфильтровывал знак плюс, если окружен пробелами: - /

Спасибо за вашу помощь, хотя 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();
}
...