FlexLuceneで日付フィルタリングを実現する方法

 ポイントは、以下の2点です。

  • ドキュメントの日付を、同一フィールド名でLongPointとStoredFieldを使って登録する。(17行目付近)
  • 検索時にLongPoint.NewRangeQueryを使って、絞込みを行う点です。(32行目)

実装例

public void LongPointTest() {
    var analyzer = new WhitespaceAnalyzer();
    var iwc = new IndexWriterConfig(analyzer);

    iwc.SetOpenMode(IndexWriterConfigOpenMode.CREATE);

    //テスト用インデックス作成---------------------------------------------
    DateTime baseDate = DateTime.Parse("2020/07/16 08:00:00");
    var ram = new RAMDirectory();
    var writer = new IndexWriter(ram, iwc);
    try {
        for (int i = 0; i < 10; i++) {
            var doc = new Document();
            doc.Add(new TextField("text", "hoge foo", FieldStore.YES));
            DateTime tmp = baseDate.AddDays(i);
            long l = long.Parse(tmp.ToString("yyyyMMddHHmmss"));
            //日付文字列をlong値で保持
            doc.Add(new LongPoint("date", l));
            //long値をストアするには、同じフィールド名でStoredFieldとして指定する必要がある。
            doc.Add(new StoredField("date", l));

            writer.AddDocument(doc);
        }
        
    } finally {
        writer.Close();
    }

    //検索------------------------------------------------------------
    TermQuery tq = new TermQuery(new Term("text", "foo"));
    //日付範囲の条件
    Query rq = LongPoint.NewRangeQuery("date", 20200717000000, 20200719000000);

    BooleanQueryBuilder b = new BooleanQueryBuilder();
    b.Add(tq, BooleanClauseOccur.MUST); //AND条件
    b.Add(rq, BooleanClauseOccur.FILTER); //AND条件(スコアリングに関与しない)
    Query q = b.Build();

    DirectoryReader dr = DirectoryReader.Open(ram);
    IndexSearcher searcher = new IndexSearcher(dr);
    ScoreDoc[] hits = searcher.Search(q, 100).ScoreDocs;
    for (int i = 0; i < hits.Length; i++) {
        var doc = searcher.Doc(hits[i].Doc);
        Debug.WriteLine(DateTime.ParseExact(doc.Get("date"), "yyyyMMddHHmmss", null));
    }
}

検索結果

2020/07/17 8:00:00
2020/07/18 8:00:00

全文検索の仕組み

全文検索機能の仕組みには、「順次検索方式」、「転置インデックス方式」の2つがあります。

・順次検索方式の特徴
・インデックスを使わない検索なので、すぐにでも検索を実行できる。
・大量ドキュメントの検索では膨大な時間がかかる。 
利用例)grepコマンド 
・転置インデックス方式の特徴
・検索を実行する前にインデックスを作成しておく必要がある。
・大量ドキュメントでも高速に検索することができる。

・転置インデックスの作成方法
1.形態素解析を行う
①.分割
すもも/も/もも/も/もも/の/うち
②.品詞/活用の判定
すもも(名詞)/も(助詞)/もも(名詞)/も(助詞)/もも(名詞)/の(助詞)/うち(副詞)
③.検索で不要な助詞、副詞を削除
すもも/もも
 2.単語の出現頻度をカウント
     例) 
文章1:「選択したドキュメントの内容をプレビュー表示します。」
文章2:「Officeドキュメントをプレビュー表示します。」
選択 ドキュメント 内容 プレビュー 表示 Office
文章1 1 1 1 1 1 0
文章2 0 1 0 1 1 1
 
・代表的な日本語形態素解析エンジン
・MeCab:語や辞書、またデータベース化された言語資料であるコーパスに依存しない、汎用的な設計がMeCabの特徴です。
・JUMAN:京都大学大学院情報学研究科知能情報学専攻の黒橋・河原研究室が開発した形態素解析ツールです。Wikipediaから抽出した辞書を使用することができます。
・Kuromoji:MeCab-IPADIC辞書を内包しており、Apache Lucene, Apache Solrの日本語対応の土台となっています。

・言語に依存しない分割手法
・N-Gram
隣接したN個の記号毎の出現頻度を集計。 

   例)すもももももももものうち 
uni-gram bi-gram tri-gram
文字 度数 相対度数 文字 度数 相対度数 文字 度数 相対度数
1 0.083 すも 1 0.091 すもも 1 0.100
8 0.667 もも 7 0.636 ももも 6 0.600
1 0.083 もの 1 0.091 ももの 1 0.100
1 0.083 のう 1 0.091 ものう 1 0.100
1 0.083 うち 1 0.091 のうち 1 0.100

Pokuda Search Proでは、Kuromojiを利用した転置インデックス方式の検索方法を採用しております。これにより大量なドキュメントでも高速に検索できるようになっています。

FlexLuceneで「もしかして検索」を実装する方法

 今回は、FlexLuceneのFuzzySuggesterの使い方をご紹介します。

  • 以下のコードで、"Content"にある転置インデックスからFuzzySuggesterの結果を確認することがきます。
    private void FuzzySuggestTest() {

        java.nio.file.Path idxPath = FileSystems.getDefault().getPath(storePath);
        var fsDir = FSDirectory.Open(idxPath);
        var idxReader = DirectoryReader.Open(fsDir);

        Dictionary dictionary = new LuceneDictionary(idxReader, "Content");
        var directory = new RAMDirectory();
        var suggester = new FuzzySuggester(directory, "", new JapaneseAnalyzer());
        suggester.Build(dictionary);

        //最大3候補を表示
        var resultList = suggester.Lookup("単体", false, 3);
        int cnt = 0;
        for (int i = 0; i < resultList.size(); i++) {
            var lr = (FlexLucene.Search.Suggest.LookupLookupResult)resultList.get(i);
            string keyword = lr.Key.toString();
            Debug.WriteLine(keyword);
        }
    }
  • FuzzySuggesterの結果

後は、抽出した「もしかして」キーワードで再検索できるように実装すれば、「もしかして検索」機能を実現できます。

FlexLuceneで形態素解析

 このFlexLucene v6.3.0のJapaneseAnalyzerでは、形態素解析エンジンにKuromojiが採用されています。今回は、FlexLuceneのJapaneseAnalyzerの形態素解析結果を確認する方法をご紹介します。

  • 以下のコードで、文章の分割結果を確認することがきます。
    private void ShowToken() {
        var sr = new java.io.StringReader("讃岐うどんを食べる。");
        var stream = new JapaneseAnalyzer().TokenStream(" ", sr);

        java.lang.Class ct = java.lang.Class.forName(typeof(CharTermAttribute).AssemblyQualifiedName);
        var charTerm = stream.AddAttribute(ct);

        stream.Reset();
        while (stream.IncrementToken()) {
            Console.WriteLine(charTerm.ToString());
        }
    }
  • 形態素解析後の結果

無料版のMicrosoft Teamsのリモート操作でサーバーをメンテナンス

前回、紹介させて頂きました、「無料版のMicrosoft TeamsでゲストユーザとWeb会議をする方法」の応用例です。

在宅勤務や、出張自粛が励行される中でも、お客さんのサーバをメンテする必要がでることもあると思います。
また、サーバのメンテにおいては、サーバー室に出入りせずに、リモートデスクトップで行うケースも多いと思います。
今回は、Microsoft Teamsと、リモートデスクトップを活用して、リモートでサーバメンテを実施する方法についてです。

接続のイメージは以下のとおりです。


メンテ対象サーバーへの接続の流れは以下の通りです。





ポイントは、⑧の部分でウィンドウを小さくしておく点です。
これにより、被サポート側は、自分のPCで別作業を行いながら、サポートを受けることができます。
また、現段階では、接続上限時間は8時間となっていますので、長時間のメンテナンスでも活用できそうです。

コロナ騒動前は、セキュリティのしっかりしたリモートサポートツールを導入しようとすれば、
年間数十万円のライセンス料も珍しくなかったのですが、今回の方法だと無料です。

コロナ騒動での外出禁止のなかでの「事業継続」、「移動時間の節約」と重宝しております。


厳選 Visual Studioの便利なショートカット

  エラー箇所にジャンプ 「Ctrl + Shift + F12」 ブレークポイント 設定/解除 「F9」 有効化/無効化 「Ctrl + F9」 ViEmu特有 「:ls」:バッファナンバーのリストを表示。 「:b2」:バッファ2のファイルを開く。 「:n」:次のバッファのファ...