[PC] FlexLuceneでソート(その1)~Javaで記載されていたソートのサンプルをC#にしてみました~

FlexLuceneでソート

本家Luceneを使ったソートのサンプル(Java)を見つけました。さっそくC#にしてみました。

移植

基本的な構造部分は、簡単に置換で書き換えてしまいます。

変更前:import org.apache.lucene.
変更後:using FlexLucene.

その他、throuw Exceptionは、外してしまいました。Javaは、camelCaseなのに対して、C#は、PascalCaseなので、関数の名前とかも入れ替えました。

変更点

JavaとC#との差の他にLuceneのバージョンの違いなのか、サンプルは「Field.Store.YES」→C#は「FieldStore.YES」の違いがありました。これは、以前に遭遇していたのですんなり対応できました。

ソートの変更点

ソートに関わる部分は、インデックスを作る際にソートの対象となるFieldの追加するSortedDocValuesField()関数です。ソートに使う項目を指定し、値を保存しておきます。
doc.Add(new SortedDocValuesField(“date”, new BytesRef(date) ));

検索する際は、ソートの対象となる項目を指定するSort()関数と、Search()関数のパラメータ設定とが新しい設定項目です。Sort()関数は、複数の項目を指定することができるようです。下の例は、第一優先として”date”の項目でソートし、次にScoreでソートするようです。Search()の第3引数は、上記のSort()で作成したsortを代入するのと、第4引数は、Scoreを使うかどうか、第5引数は、maxScoreを得るか否かの指定だそうです。パフォーマンスを気にする場合は、maxScoreは、falseにすることを推奨しています。私は、サンプルそのままにtrueにしています。
Sort sort = new Sort(new SortField(“date”, SortFieldType.STRING, true), SortField.FIELD_SCORE);
TopDocs docs = idxSearcher.Search(query, 10, sort, true, true);

using System;
using FlexLucene.Analysis;
using FlexLucene.Analysis.Standard;
using FlexLucene.Document;
using FlexLucene.Index;
using FlexLucene.Search;
using FlexLucene.Store;
using FlexLucene.Util;
using java.io;

namespace TestSort
{
    class Program
    {
        public static Analyzer analyzer = new StandardAnalyzer();
        public static IndexWriterConfig config = new IndexWriterConfig(analyzer);
        public static RAMDirectory ramDirectory = new RAMDirectory();
        public static IndexWriter indexWriter;

        static void Main(string[] args)
        {
            CreateIndex();
            SearchSingleTerm("title", "lucene");
            ramDirectory.Close();
        }

        public static void createDoc(String author, String title, String date) 
        {
            Document doc = new Document();
            doc.Add(new TextField("author", author, FieldStore.YES));
            doc.Add(new TextField("title", title, FieldStore.YES));
            //doc.add(new Field ("date", date, Field.Store.YES, Field.Index.NOT_ANALYZED));
            doc.Add(new SortedDocValuesField("date", new BytesRef(date) ));
            doc.Add(new StoredField("date", date));
 
            indexWriter.AddDocument(doc);
        }

        public static void CreateIndex()
        {
            try
            {
                indexWriter = new IndexWriter(ramDirectory, config);
                createDoc("Sam", "Lucece index option analyzed vs not analyzed", "2016-12-12 20:19:57");
                createDoc("Sam", "Lucene field boost and query time boost example", "2016-03-16 16:57:44");
                createDoc("Jack", "How to do Lucene search highlight example", "2016-03-16 17:47:38");
                createDoc("Smith", "Lucene BooleanQuery is depreacted as of 5.3.0", "2015-04-30 11:44:25");
                createDoc("Smith", "What is term vector in Lucene", "2015-04-10 20:33:53");

                indexWriter.Close();
            }
            catch (IOException  ex) {
                System.Console.WriteLine("Exception : " + ex.getLocalizedMessage());
            }
        }
        public static void SearchIndexNoSortAndDisplayResults(Query query)
        {
            try
            {
                IndexReader idxReader = DirectoryReader.Open(ramDirectory);
                IndexSearcher idxSearcher = new IndexSearcher(idxReader);

                TopDocs docs = idxSearcher.Search(query, 10);
                System.Console.WriteLine("length of top docs: " + docs.ScoreDocs.Length);
                foreach (ScoreDoc doc in docs.ScoreDocs)
                {
                    Document thisDoc = idxSearcher.Doc(doc.Doc);
                    System.Console.WriteLine(doc.Doc + "\t" + thisDoc.Get("author")
                            + "\t" + thisDoc.Get("title"));
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            finally
            {
            }
        }
        public static void SearchIndexAndDisplayResults(Query query)
        {
            try
            {
                IndexReader idxReader = DirectoryReader.Open(ramDirectory);
                IndexSearcher idxSearcher = new IndexSearcher(idxReader);

                Sort sort = new Sort(new SortField("date", SortFieldType.STRING, true), SortField.FIELD_SCORE);

                TopDocs docs = idxSearcher.Search(query, 10, sort, true, true);
                System.Console.WriteLine("length of top docs: " + docs.ScoreDocs.Length + " sort by: " + sort);
                foreach (ScoreDoc doc in docs.ScoreDocs)
                {
                    Document thisDoc = idxSearcher.Doc(doc.Doc);
                    System.Console.WriteLine(doc.Doc + "\t" + thisDoc.Get("author")
                            + "\t" + thisDoc.Get("title")
                            + "\t" + thisDoc.Get("date"));
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            finally
            {
            }
        }
        public static void SearchSingleTerm(String field, String termText)
        {
            Term term = new Term(field, termText);
            TermQuery termQuery = new TermQuery(term);

            SearchIndexAndDisplayResults(termQuery);
            SearchIndexNoSortAndDisplayResults(termQuery);
        }
    }
}

以上のコードでコンパイルと動作確認を実施しました。Visual Studioをお使いの人は是非お試しください。

まとめ

Lucene 5.3を使ったサンプルサイトを見つけました。Luceneのバージョン2.9を使っていた私にとって新しいことがいろいろ書いてあるので、これをFlexLuceneに変換していろいろ試していこうかと思います。もしご興味があれば今後ともご参照ください。少しでもみなさまのお役に立てれば幸いです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です