Сортировка Lucene.net 2.9.2 (сортировка не работает) - PullRequest
6 голосов
/ 21 декабря 2010

У меня проблема с сортировкой индекса lucene.net в .NET.Я попробовал почти все решения на stackoverflow и искал ответы Google.Я использую Lucene.NET 2.9.2 и ASP.NET 2.0.Я хочу отсортировать строки, как в sql, вы можете напечатать 'order by Title desc [asc]'

Я покажу вам мой код, и я надеюсь, что кто-то может мне помочь.

    //Here I create Index with some fields
    doc.Add(new Field("prod_id",row["prod_id"].ToString(),Field.Store.YES,Field.Index.ANALYZED));
            doc.Add(new Field("prod_title", row["prod_title"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("prod_desc", row["prod_desc"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("prod_author", row["prod_author"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("prod_publisher", row["prod_publisher"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field("prod_price", row["prod_price"].ToString(), Field.Store.YES, Field.Index.ANALYZED));

//Then next I try to do search with sort option:

//method for return approciate Sort object
private static Sort SetSortForLucene(string _sort)
    {
        Sort sort;
        switch (_sort)
        {
            case "UnitPriceGorss":
                sort = new Sort(new SortField("prod_price",SortField.DOUBLE,false);
                break;

            case "UnitPriceGorssDESC":
                sort = new Sort(new SortField("prod_price",SortField.DOUBLE,true);
                break;

            case "Title":
                //not working
                sort = new Sort(new SortField("prod_title", SortField.STRING, true));
                break;

            case "TitleDESC":
                //not working
                sort = new Sort(new SortField("prod_title", SortField.STRING, false));
                break;
            case "":
                sort = new Sort(new SortField("prod_title", SortField.STRING, false));
                break;
            default:
                sort = new Sort(new SortField("prod_title", SortField.STRING, false));
                break;
        }
        return sort;
    }
//Inside my query of lucene method:
StandardAnalyzer analizer = new StandardAnalyzer(Version.LUCENE_29);
IndexReader reader =IndexReader.Open(IndexPath);
Searcher searcher = new IndexSearcher(reader);
//Here call for Sort object
Sort sort = SetSortForLucene(_sort);
TopFieldDocCollector collector = new TopFieldDocCollector(reader, sort, pageSize);
//Find which document field need to me asked in QueryParser object
string _luceneField = "";

        if (luceneField.Contains("_"))
            _luceneField = luceneField;
        else
        switch (luceneField)
        {
            case "Title": _luceneField = "prod_title"; break;
            case "Description": _luceneField = "prod_desc"; break;
            case "Author": _luceneField = "prod_author"; break;
            case "Publisher": _luceneField = "prod_publisher"; break;
            default: _luceneField = "prod_title"; break;
        }
        QueryParser parser = new QueryParser(_luceneField, analizer);
        Query query = parser.Parse(luceneQuery);
        ScoreDoc[] hits;
        searcher.Search(query,collector);
//Obtaining top records from search but without any sort.
        hits =  collector.TopDocs().scoreDocs;

        foreach (ScoreDoc hit in hits)
        {
            Document doc = searcher.Doc(hit.doc);
            string a = doc.Get("prod_id");
            int id = 0;
            if (hit.score > score)
            {
                if (int.TryParse(doc.Get("prod_id"), out id))
                                tmpId.Add(id);
            }
        }
//I also define stop words for full text searching and i think this is
//real cause of problem with sorting.
System.String[] stopWords = new System.String[]{"a","że","w","przy","o","bo","co","z","za","ze","ta","i","no","do"};

Я использовал эту ссылку в stackoverflow. и эту симпатичную ссылку , чтобы решить мою проблему, но сортировка не удалась, и я не знаю, что не так с моим кодом.

Через несколько дней я наконец нашел решение.Поле, которое я хочу отсортировать, не должно быть токенизированным, когда оно представляет строковое значение.

Например, когда я хочу отсортировать товары по названию (ASCENDING / DESCENDING), вы должны указать что-то вроде этого:

doc.Add(new Field(Product.PROD_TITLE_SORT, row["prod_title"].ToString().Replace(" ", "_") + "_" + row[Product.PROD_ID].ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));

То, что я не получаю, это факт, почему это поле нехранение и не анализ и, следовательно, lucene.net может сортировать по этому добавленному полю.Это поле сортировки даже не в индексе !!Я проверил в браузере индексов lukeall-1.0.1.jar.

Во-вторых, вам нужно создать правильный метод сортировки:

private static Sort SetSortForLucene(string _sort)
        {
            Sort sort;
            _sort = !string.IsNullOrEmpty(_sort) ? _sort : "";
            switch (_sort)
            {
                case "UnitPriceGorss":
                    sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, false));
                    break;

                case "UnitPriceGorssDESC":
                    sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, true));
                    break;

                case "Title":
                    //not it works perfectly.
                    sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, true));
                    break;

                case "TitleDESC":
                    //not it works perfectly.
                    sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, false));
                    break;
                case ""://Here is default sorting behavior. It get's result according to Lucene.NET search result score.
                    sort = new Sort(SortField.FIELD_SCORE);
                    break;
                default:
                    sort = new Sort(SortField.FIELD_SCORE);
                    break;
            }
            return sort;
        }

Что меня действительно подозревает, так это то, что сортировка работает с SortField.DOUBLE, когда поле индексируется в полнотекстовом индексе lucene.

Надеюсь, этот пост поможет всем, у кого есть похожие проблемы с сортировкой.

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

Поле не нужно сохранять, если вы не возвращаете данные в своем запросе. Однако он все еще добавляется в индекс.

Причина, по которой вы не анализируете поле, по которому хотите сортировать, состоит в том, что анализатор разбивает поле на отдельные термины, что делает сортировку очень сложной, поскольку в индексе документа будет несколько слов, которые, очевидно, не могут быть отсортированы против всего индекса. Это относится ко всем типам полей, независимо от того, являются ли они одним термином или нет.

Полагаю, вы можете сохранить поле, но если вы не хотите вернуть его в своем запросе, в этом нет необходимости.

4 голосов
/ 17 января 2011

одна важная вещь, которую я подозреваю знать о сортировке.

Она не работает с токенизированными (проанализированными) данными.

...