Lucene.net не может найти ".net" - PullRequest
1 голос
/ 20 января 2012

Q1: я делаю поиск, используя Lucene. Все работает отлично и быстро. Когда я попытался найти фразу «.net», ничего не нашел. Может быть, вы знаете, как я могу справиться с этим.

Q2: Как я могу искать и игнорировать регистр?

Обновление 1

Q1: я сохраняю задания, используя SimpleLucene . Вот код:

DirectoryIndexWriter _indexWriter = new DirectoryIndexWriter(new DirectoryInfo(indexPath), true);
using (var indexService = new IndexService(_indexWriter))
{
   var result = indexService.IndexEntities(jobsTempArray, new JobIndexDefinition());
   Console.WriteLine("{0} products indexed in {1} milliseconds.", result.Count, result.ExecutionTime);
}

Файл JobIndexDefinition:

public class JobIndexDefinition : IIndexDefinition<LucenceJobModel>
{
    public Document Convert(LucenceJobModel job)
    {
        var document = new Document();

        document.Add(new Field("jobtitle", job.JobTitle, Field.Store.YES, Field.Index.ANALYZED));
        document.Add(new Field("AreaCode", job.AreaCode.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Company", job.Company, Field.Store.YES, Field.Index.NOT_ANALYZED));
        var dateValue = DateTools.DateToString(job.DatePosted.Value, DateTools.Resolution.MILLISECOND);
        document.Add(new Field("DatePosted", dateValue, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Description", job.Description, Field.Store.YES, Field.Index.ANALYZED));
        document.Add(new Field("Expierence", job.Expierence, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("JobType", job.JobType, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Link", job.Link, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("LinkId", job.LinkId.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Location", job.Location, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("PayRate", job.PayRate, Field.Store.YES, Field.Index.NOT_ANALYZED));

        document.Add(new Field("Source", job.Source, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("TaxTerm", job.TaxTerm, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Term", job.Term, Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Title", job.Title, Field.Store.YES, Field.Index.NOT_ANALYZED));

        return document;
    }

    public Term GetIndex(LucenceJobModel job)
    {
        return new Term("Link", job.Link);
    }
}

Я ищу поля JobTitle, Description и DatePosted. Вот код поиска:

public List<LucenceJobModel> JobsSearch(string keyword, string location, PageInfo pageInfo)
{
    string[] words = keyword.Split(new[] { ' ' });

    IndexReader reader = IndexReader.Open(SmartSearch.Instance.GetDirectory(), true);
    var searcher = new IndexSearcher(reader);

    var standardAnalyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
    var fields = new[] { "JobTitle", "Description", "DatePosted" };

    var searchQuery = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, fields, standardAnalyzer);
    //searchQuery.SetAllowLeadingWildcard(true);

    // perform the search
    var query = new BooleanQuery();

    foreach (var word in words)
    {
        if (!String.IsNullOrEmpty(word))
        {
            var qTemp = searchQuery.Parse(word);
            var q = searchQuery.Parse(qTemp.ToString().Substring(qTemp.ToString().LastIndexOf(":") + 1) + "*");
            query.Add(q, BooleanClause.Occur.MUST);
        }
    }

    int maxDocs = 1;
    if (reader.MaxDoc() > 0)
        maxDocs = reader.MaxDoc();

    var results = searcher.Search(query, filter, maxDocs);
    foreach (var scoreDoc in results.scoreDocs)
    {
        var document = searcher.Doc(scoreDoc.doc);
    }

    var jobs = new List<LucenceJobModel>();
    for (int i = 0; i < results.scoreDocs.Length; i++)
    {
        var document = searcher.Doc(results.scoreDocs[i].doc);
        if (i >= (pageInfo.CurrentPage - 1) * pageInfo.ItemsPerPage && i < pageInfo.CurrentPage * pageInfo.ItemsPerPage)
        {
            jobs.Add(LucenceJobModel.ConvertFromDoc(document));
        }

        itemsForGroup.Add(new ItemGroupFor
            {
                Company = document.GetField("Company").StringValue(),
                DatePosted = DateTools.StringToDate(document.GetField("DatePosted").StringValue()),
                JobType = document.GetField("JobType").StringValue(),
                Location = document.GetField("Location").StringValue(),
                Source = document.GetField("Source").StringValue(),
                Title = document.GetField("Title").StringValue()
            });
    }

    pageInfo.TotalItems = results.scoreDocs.Length;
    return jobs;
}

Я хочу иметь возможность искать ключевые слова, такие как "C #" или ".net", не удаляя "#" или ".".

Q2: я ищу в поле Местоположение. Вот код:

public List<string> GetLocations(string term)
{
    IndexReader reader = IndexReader.Open(SmartSearch.Instance.GetDirectory(), true);
    var searcher = new IndexSearcher(reader);

    var standardAnalyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
    QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Location", standardAnalyzer);
    string str = parser.Parse(term).ToString().Substring(parser.Parse(term).ToString().LastIndexOf(":") + 1);

    PrefixQuery q = new PrefixQuery(new Term("Location", string.Format("{0}", str)));

    TopDocs results = searcher.Search(q, 5000);

    return results
                .scoreDocs
                .Select(x => searcher.Doc(x.doc))
                .Select(x => x.GetField("Location").StringValue())
                .Distinct()
                .ToList();
}

Я хочу найти «Нью-Йорк», «Нью-Йорк» и так далее. Но я знаю, что он ищет, только если дело верно.

Ответы [ 2 ]

4 голосов
/ 22 января 2012

Я не знаком с "SimpleLucene", но ваш код выглядит намного сложнее, чем нужно.

Несколько вещей:

Имена полей чувствительны к регистру, вы сохраняете название вакансии как "jobtitle", но ищите его, используя "JobTitle".Они должны соответствовать.

Вы упомянули, что хотите выполнить поиск в полях DatePosted и Location, но они указаны как "NOT_ANALYZED" в опубликованном вами коде.Измените его на «ANALYZED», если вы хотите искать в этих полях.

Попробуйте анализатор пробелов, если вы хотите сохранить такие термины, как «.net» и «C #».Помните, что анализатор пробелов не использует строчный фильтр, поэтому поиск по «.NET» не будет соответствовать «.net».Возможно, вам придется написать собственный анализатор.

A1: Все встроенные анализаторы (кроме ключевого слова и пробела) отбирают период из термина, поэтому не должно иметь значения, если вы ищете: "net", ".net", ".net", ... net ... "и т. д. Если это не так, возникает другая проблема. Отправьте код и, возможно, мы поможем.

Если вам нужно сопоставить такие термины, как ".net" и "C #", вам, вероятно, повезет больше с анализатором пробелов. Если это не отвечает вашим потребностям, вам, вероятно, придется написать собственный анализатор.

A2: Стандартные анализаторы автоматически преобразуют верхний регистр в нижний регистр, поэтому регистр уже для вас игнорируется.

На этой странице есть хорошие примеры того, что различные анализаторы делают с фразой.

со страницы выше:

Анализ "Быстрая коричневая лиса перепрыгнула через ленивых собак"

org.apache.lucene.analysis.WhitespaceAnalyzer:
    [The] [quick] [brown] [fox] [jumped] [over] [the] [lazy] [dogs] 

org.apache.lucene.analysis.SimpleAnalyzer:
    [the] [quick] [brown] [fox] [jumped] [over] [the] [lazy] [dogs] 

org.apache.lucene.analysis.StopAnalyzer:
    [quick] [brown] [fox] [jumped] [over] [lazy] [dogs] 

org.apache.lucene.analysis.standard.StandardAnalyzer:
    [quick] [brown] [fox] [jumped] [over] [lazy] [dogs] 

org.apache.lucene.analysis.snowball.SnowballAnalyzer:
    [quick] [brown] [fox] [jump] [over] [lazi] [dog] 

Анализ "XY & Z Corporation- xyz@example.com "

   org.apache.lucene.analysis.WhitespaceAnalyzer:
        [XY&Z] [Corporation] [-] [xyz@example.com] 

    org.apache.lucene.analysis.SimpleAnalyzer:
        [xy] [z] [corporation] [xyz] [example] [com] 

    org.apache.lucene.analysis.StopAnalyzer:
        [xy] [z] [corporation] [xyz] [example] [com] 

    org.apache.lucene.analysis.standard.StandardAnalyzer:
        [xy&z] [corporation] [xyz@example] [com] 

    org.apache.lucene.analysis.snowball.SnowballAnalyzer:
        [xy&z] [corpor] [xyz@exampl] [com] 
2 голосов
/ 20 января 2012

A1:

Это сильно звучит, поскольку вы не будете использовать тот же Analyzer / Tokenizer для индексации и для запросов.

Вы должны убедиться, что оба они одинаковыдля того же поля.Например,

Если при индексировании создается термин .net, а анализатор запросов удаляет точки, он ничего не найдет.

A2: StandardAnalyzer должен позаботиться об этом.

...