LoginSignup
1
1

More than 1 year has passed since last update.

【ElasticSearch】bulkAPIを用いたデータ登録および検索をC#で試してみた

Posted at

はじめに

ElasticSearchを使ってみたい!という興味方位からElasticSearch導入~Webアプリケーションにて検索までを実施してみた。
ほぼほぼ初心者なのでお手柔らかにお願いします。
※今回はIndex定義やMapping定義などをせず、とりあえず検索したいというレベルで開発しています。

Elastic Search導入編

下記URLを参考にElasticSearchとKibanaをインストールする
https://qiita.com/azumabashi/items/a6d989f02bf0e369023a

Elasticsearch と Kibana 7.5.1 Windows をインストールしてみる

とりあえず使いたいレベルであればデータ登録時にIndexが自動生成されるっぽい
image.png

データ登録をKibanaで一つずつ作るのは面倒くさいので、C#のConsoleアプリケーションをVisual Studioで開発する。
データ登録は下記URLにあるbulkAPIを用いる
https://qiita.com/mino_s2000/items/191817f9d1d16320c478

NEST Tips - Elasticsearch .NET Client

開発方針

下記方針で開発を行った。
前提:タイトルからURLを取得するといったツールを作成する
①Consoleアプリケーションにて登録したいデータをcsvからデータ取得し、bulkAPIを用いてIndexに投入する
②MVC WebアプリケーションにてElasticSearchを用いて検索を行い、画面に検索結果を表示させる。

実際に作成したコードを下記に記載する

バッチ

Program.cs
// 検索用(登録用のバッチのため不要)
//ElasticSearch.SearchData("API");

// 登録用
// CSVからデータ取得
var list = FileOperationService.GetCsvFileForElasticSearchData();
ElasticSearch.RegistData(list);
ElasticSearch.cs
static class ElasticSearch
{
    public static string ApiUrl = "http://localhost:9200";
    public static string IndexName = "testindex";
    public static ConnectionSettings settings = new ConnectionSettings(new Uri(ApiUrl));
    public static ElasticClient client = new ElasticClient(settings.DefaultIndex(IndexName));


    public static void SearchData(string searchWord)
    {
        IList<IndexModel> hits = new List<IndexModel>();

        try
        {
            var response = client.Search<IndexModel>(s => s.Size(10)
            .Query(q => q.MatchPhrasePrefix(m => m.Field(f => f.title).Query(searchWord))));

            foreach (var hit in response.Hits)
            {
                hits.Add(hit.Source);
                Console.WriteLine("id:" + hit.Source.id);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.WriteLine("検索結果:" + hits.Count);
        Console.WriteLine("何かキーを押してください");
        Console.ReadKey();
    }

    public static void RegistData(List<IndexModel> indexModel)
    {
        var docList = new List<IndexModel>();
        foreach (var index in indexModel)
        {
            docList.Add(new IndexModel
            {
                id = index.id,
                title = index.title,
                path = index.path,
                description = index.description
            }
            );
        }
        var res = client.Bulk(e => e
                .Index(IndexName)
                .IndexMany(docList));

    }
}
IndexModel.cs
namespace ConsoleElasticSearchSample.Model
{
    class IndexModel
    {
        public string id { get; set; }
        public string title { get; set; }
        public string path { get; set; }
        public string description { get; set; }
    }
}
FileOperationService.cs
static class FileOperationService
{
    public static string FilePath = @"C:\work\elasticsearch\";
    public static List<IndexModel> GetCsvFileForElasticSearchData()
    {
        // 配列からリストに格納する
        var indexList = new List<IndexModel>();

        // 読み込みたいCSVファイルのパスを指定して開く
        using (var sr = new StreamReader(FilePath + "elasticsearch.csv"))
        {
            // 末尾まで繰り返す
            while (!sr.EndOfStream)
            {
                // CSVファイルの一行を読み込む
                string line = sr.ReadLine();
                // 読み込んだ一行をカンマ毎に分けて配列に格納する
                string[] values = line.Split(',');

                var index = new IndexModel();
                index.id = values[0];
                index.title = values[1];
                index.path = values[2];
                index.description = values[3];
                indexList.Add(index);
            }
        }

        return indexList;
    }
}

オンライン

共通処理はバッチを参照

HomeController.cs
public ActionResult About()
{
    ViewBag.Message = "ElasticSearchの結果を表示します";
    var list = ElasticSearch.SearchData("ela");
    ViewBag.list = list;

    return View();
}
About.cshtml
@{
    ViewBag.Title = "About";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>

<p>
    <table class="table table-responsive">
        <tr>
            <th>id</th>
            <th>title</th>
            <th>path</th>
            <th>description</th>
        </tr>
        @for (var i = 0; i < ViewBag.list.Count; i++)
        {
    <tr>
        @{
            <th>@ViewBag.list[i].id</th>
            <th>@ViewBag.list[i].title</th>
            <th><a href="@ViewBag.list[i].path" target="_blank">@ViewBag.list[i].path</th>
            <th>@ViewBag.list[i].description</th>
        }

    </tr>
        }
    </table>

</p>

CSV

elasticsearch.csv
id,title,path,description
1,Elasticsearch と Kibana 7.5.1 Windows をインストールしてみる,https://qiita.com/azumabashi/items/a6d989f02bf0e369023a,https://db-engines.com/en/ranking によると、サーチエンジンのElasticsearchはかなりいいところ(2019年12月付で全体の8位、サーチエンジンではトップ)につけています。
2,NEST Tips - Elasticsearch .NET Client,https://qiita.com/mino_s2000/items/191817f9d1d16320c478,川崎フロンターレ、J1初優勝おめでとうございます!等々力に行きたかったです。
3,Python Elasticsearch 基本的な使い方まとめ,https://qiita.com/satto_sann/items/8a63761bbfd6542bb9a2,PythonでElasticsearchを使う機会があったため情報を収集していましたが、サイトで使われているElasticsearchのバージョンが古かったり、そもそも、情報が少なかったりしたので、今回、メモとして簡単な例と共に基本的な使い方をまとめました。

開発メモ

bulkAPIには「NEST」を使用しました。
NESTをVisual Studioで使用するためには、Nugetパッケージから「NEST」で検索を行い、最新バージョンをインストールすることで使用することができます。
image.png

image.png

暫定版画面

titleフィールドに登録されている「ela」を検索した結果が下記となる
image.png
入力エリアを用意して、AjaxにてElasticSearchを呼び出す仕組みを用意するとよりよいだろう。

ElasticSearchのメモ

今回検索にて「elastic」などで検索してもヒットしない現象が起きました。

GET testindex/_search
{
  "query" : {
    "match": {
      "title": "elastic"
    }
  }
}

ElasticSearchでは"match"は完全一致検索となるため、部分一致検索をしたい場合は"match_phrase_prefix"を使用しないといけないみたいです。
知らなかった。。。

GET testindex/_search
{
  "query" : {
    "match_phrase_prefix": {
      "title": "elastic"
    }
  }
}

上記であれば検索可能。

最後に

今後はIndex、Mapping定義をしっかりと実施したいのと、ElasticSearchの性能検証など試してみる。
あとは検索クエリのまとめとかやってみようかなーと。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1