2018-11-17 Elasticsearch .NET client 笔记

问题描述

  1. 使用Elasticsearch .NET client 创建ES的实例,并导入Shapefile数据建全文索引和空间索引。
  2. Shapefile为地址点数据,需要对指定的字段进行全文检索(分词、拼音),支持范围搜索

ES服务端配置

  1. ES的版本为6.3.0
  2. 采用ik插件进行分词
  3. 采用pinyin插件进行拼音模块
  4. 使用postman测试
#创建实例
PUT http://localhost:9200/test_index
{
    "index":{
      "analysis":{
        "analyzer":{
           "ik_pinyin_analyzer":{
            "type":"custom",
            "tokenizer":"ik_smart",
            "filter":"pinyin_filter"
          }
        },
        "filter":{
          "pinyin_filter":{
            "type":"pinyin",
            "keep_first_letter": false
          }
        }
      }   
}
    
}
#返回结果
//////////////////返回结果////////////////////////
{
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "test_index"
}

///////////////////返回结果//////////////////////
#配置Mapping
PUT http://localhost:9200/test_index/_mapping/test_type
{
  "properties": {
    "testfield":{
      "type": "text",
      "analyzer": "ik_max_word",
      "search_analyzer": "ik_smart",
      "fields": {
        "my_pinyin":{
          "type":"text",
          "analyzer": "ik_pinyin_analyzer",
          "search_analyzer": "ik_pinyin_analyzer"
        }
      }
    }
  }
}

#返回结果
//////////////////返回结果////////////////////////
{
    "acknowledged": true
}
//////////////////返回结果////////////////////////
#索引文档

POST http://localhost:9200/test_index/test_type
{
  "testfield":"今天天气不错"
}
#返回结果
//////////////////返回结果////////////////////////
{
    "_index": "test_index",
    "_type": "test_type",
    "_id": "tjDRIWcBQbCTUJC9qxCs",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}
//////////////////返回结果////////////////////////
#搜索文档(中文)
POST http://localhost:9200/test_index/test_type/_search
{
  "query":{
    "match": {
      "testfield": "天气"
    }
  }
}
#返回结果
//////////////////返回结果////////////////////////
{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.2876821,
        "hits": [
            {
                "_index": "test_index",
                "_type": "test_type",
                "_id": "tzDYIWcBQbCTUJC9HRBn",
                "_score": 0.2876821,
                "_source": {
                    "testfield": "今天天气不错"
                }
            }
        ]
    }
}
//////////////////返回结果////////////////////////


#搜索文档(拼音)
POST http://localhost:9200/test_index/test_type/_search
{
  "query":{
    "match": {
      "testfield.my_pinyin": "tianqi"
    }
  }
}
#返回结果
//////////////////返回结果////////////////////////
{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.68324494,
        "hits": [
            {
                "_index": "test_index",
                "_type": "test_type",
                "_id": "tzDYIWcBQbCTUJC9HRBn",
                "_score": 0.68324494,
                "_source": {
                    "testfield": "今天天气不错"
                }
            }
        ]
    }
}
//////////////////返回结果////////////////////////

通过以上测试,可以确定ES的服务端功能可以实现,接下来就是使用.NET客户端进行调用

ES客户端配置

  1. vs2015 .net 4.6.1
  2. nuget 安装 Es.net client

首先建立连接,本机测试是单机部署,所以连接比较简单

            var uris = new[] { new Uri("http://localhost:9200") };
            var connectionPool = new SniffingConnectionPool(uris);
            var settings = new ConnectionConfiguration(connectionPool);
            var lowlevelClient = new ElasticLowLevelClient(settings);

ElasticLowLevelClient这个类里面封装了各种操作,只需要构建请求体PostData就行。官方给出的方法是利用匿名对象或者字符串,在构造复杂对象的时候单独使用可能不够方便,可以根据情况自行调整。例如,导入的shapefile有多个字段需要分词,应当如何动态生成Mappings,还有在用bulk批量导入的时候,文档应该如何转成Postdata的格式。

目标1 根据需要分词的字段和固定的空间位置字段生成请求体

分析如下:层次较多,且有动态生成的内容,使用字符串format的方法比较难控制。所以固定属性名的采用匿名对象的方式,而属性名动态生成的部分,用Dictionary<string, object>来解决。

ps C# 中 string.format()的字符串中如果本来有“{}”,需要写成“{{}}”

 public static object setMapping(List<string> splitFields)
        {
            #region 配置模板
            var pinyin_filter_TEMPLATE = new
            {
                type = "pinyin",
                keep_first_letter = false
            };
            var ik_pinyin_analyzer_TEMPLATE = new
            {
                type = "custom",
                tokenizer = "ik_smart",
                filter = "pinyin_filter"
            };
            var splitField_TEMPLATE = new
            {
                type = "text",
                analyzer = "ik_max_word",
                search_analyzer = "ik_max_word",
                fields = new
                {
                    my_pinyin = new
                    {
                        type = "text",
                        analyzer = "ik_pinyin_analyzer",
                        search_analyzer = "ik_pinyin_analyzer"
                    }
                }
            };
            var shape_TEMPLATE = new
            {
                type = "geo_point"

            };

            var settings = new
            {
                index = new
                {
                    analysis = new
                    {
                        analyzer = new
                        {
                            ik_pinyin_analyzer = ik_pinyin_analyzer_TEMPLATE
                        },
                        filter = new
                        {
                            pinyin_filter = pinyin_filter_TEMPLATE
                        }
                    }
                }
            };
            #endregion

            var propertiesBody = new Dictionary<string, object>();
            // 分词字段
            foreach (string field in splitFields)
            {
                propertiesBody.Add(field, splitField_TEMPLATE);
            }
            // 空间位置字段
            propertiesBody.Add("shape", shape_TEMPLATE);

            var properties = new
            {
                properties = propertiesBody
            };
            var indexNameTEMPLATE = new Dictionary<string, object>();
            // type "addorpoi" ,可以用变量代替,一般type是自定义的
            indexNameTEMPLATE.Add("addorpoi", properties);

            var mappings = indexNameTEMPLATE;

            var settinMapping = new
            {
                settings = settings,
                mappings = mappings
            };

            return settinMapping;
        }
目标2 根据空间位置和指定间距进行地址搜索

分析如下:搜索的请求体固定,只要换参数即可,也可以使用字符串,虽然不太简洁,但是也是一种思路。
原有的查询字符串

{
"query":{
    "bool":{
        "must":{
            "match_all":{}
            },
        "filter":{
            "geo_distance":{
                "distance":"100m",
                "shape":"30.6321727220001,120.308015149"
            }
            }
        }
    }

}

使用https://www.sojson.com/yasuoyihang.html提供的压缩转义工具,获得一行转义的json字符串,再用文本把{换成{{ 同时}换成}},然后把参数扣掉换成format需要的形式。

var searchStr = string.Format(searchTemplate, "30.6321727220001,120.308015149", "100");
vat postbody = PostData.String(searchStr);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,694评论 0 3
  • 只想知道大家的工作状态
    幽默的老黑阅读 219评论 0 0
  • 落实“五化”教学之反思 本周开展了以“在课堂教学中如何落实‘五化’教学流程”为主题的教学研讨活动,老师们针对自己近...
    小亮_f6c6阅读 177评论 0 0
  • 要理解static,就必须要先理解另一个与之相对的关键字,很多人可能都还不知道有这个关键字,那就是auto,其实...
    萤火虫的梦想阅读 1,103评论 0 0