ElasticSearch.NET & NEST —— C#的ES驱动使用入门

NEST 基础使用

1. 建立连接,创建client

var nodes = new[]
            {
    new Uri("http://localhost:9200")
};

var pool = new StaticConnectionPool(nodes);
var settings = new ConnectionSettings(pool); ;
var client = new ElasticClient(settings);

2.获取所有索引

var indexs = client.Cat.Indices();

3. 创建一个索引

  • 可以增加多个map 之类,多个之类相当于属性拼成了一个大表
  • subClass1 与 subClass2之间如果有重复名称的字段,那么先map的会保留,后续的不会覆盖前面的同名字段 —— 如下例:先map的Company,后map的Employee,那么生成index的时候,实际生成的是Company
    的 字段, 也就是 string 类型的 Name
client.Indices.Create("indexTest1", c => c
    .Map(m => m
        .AutoMap<Company>()
        .AutoMap<Employee>()
    )
);
public abstract class Document
{
    public JoinField Join { get; set; }
}
public class Company : Document
{
    public string Name { get; set; }
    public List<Employee> Employees { get; set; }
}
public class Employee : Document
{
    public int Name { get; set; }
    public int Salary { get; set; }
    public DateTime Birthday { get; set; }
    public bool IsManager { get; set; }
    public List<Employee> Employees { get; set; }
    public TimeSpan Hours { get; set; }
}
image.png

4. 给Es的对象加上对应的解析特性

[ElasticsearchType(RelationName = "employee")]
public class Employee
{
    [Text(Name = "first_name", Norms = false, Similarity = "LMDirichlet")]
    public string FirstName { get; set; }

    [Text(Name = "last_name")]
    public string LastName { get; set; }

    [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)]
    public int Salary { get; set; }

    [Date(Format = "MMddyyyy")]
    public DateTime Birthday { get; set; }

    [Boolean(NullValue = false, Store = true)]
    public bool IsManager { get; set; }

    [Nested]
    [PropertyName("empl")]
    public List<Employee> Employees { get; set; }

    [Text(Name = "office_hours")]
    public TimeSpan? OfficeHours { get; set; }

    [Object]
    public List<Skill> Skills { get; set; }
}

public class Skill
{
    [Text]
    public string Name { get; set; }

    [Number(NumberType.Byte, Name = "level")]
    public int Proficiency { get; set; }
}

5. 查询

  • 最简单的查询示例
var qr1 = client.Search<NodeLogSearchEntity>(s => s
                .Index("log.test_mix-2021.01.18")
                .Query(q => q
                    .MatchAll()
                    )
            );
  • 较为复杂的查询
var result = client.Search<VendorPriceInfo>(
                s => s
                    .Explain() //参数可以提供查询的更多详情。
                    .FielddataFields(fs => fs //对指定字段进行分析
                        .Field(p => p.vendorFullName)
                        .Field(p => p.cbName)
                    )
                    .From(0) //跳过的数据个数
                    .Size(50) //返回数据个数
                    .Query(q =>
                        q.Term(p => p.vendorID, 100) // 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型):
                        &&
                        q.Term(p => p.vendorName.Suffix("temp"), "姓名") //用于自定义属性的查询 (定义方法查看MappingDemo)
                        &&
                        q.Bool( //bool 查询
                            b => b
                                .Must(mt => mt //所有分句必须全部匹配,与 AND 相同
                                    .TermRange(p => p.Field(f => f.priceID).GreaterThan("0").LessThan("1"))) //指定范围查找
                                .Should(sd => sd //至少有一个分句匹配,与 OR 相同
                                    .Term(p => p.priceID, 32915),
                                    sd => sd.Terms(t => t.Field(fd => fd.priceID).Terms(new[] {10, 20, 30})),//多值
                                    //||
                                    //sd.Term(p => p.priceID, 1001)
                                    //||
                                    //sd.Term(p => p.priceID, 1005)
                                    sd => sd.TermRange(tr => tr.GreaterThan("10").LessThan("12").Field(f => f.vendorPrice))
                                )
                                .MustNot(mn => mn//所有分句都必须不匹配,与 NOT 相同
                                    .Term(p => p.priceID, 1001)
                                    ,
                                    mn => mn.Bool(
                                        bb=>bb.Must(mt=>mt
                                            .Match(mc=>mc.Field(fd=>fd.carName).Query("至尊"))
                                        ))
                                )
                            )
                    )//查询条件
                .Sort(st => st.Ascending(asc => asc.vendorPrice))//排序
                .Source(sc => sc.Include(ic => ic
                    .Fields(
                        fd => fd.vendorName,
                        fd => fd.vendorID,
                        fd => fd.priceID,
                        fd => fd.vendorPrice))) //返回特定的字段
               );

二、Elasticsearch的文本的查询

es的text数据存储,实际上插入一条数据的时候,会默认的分词,分词后再倒排索引,后面方便查询。text在被index的时候,会保留一个它的子字段 text.keyword,改字段是不被分词的text字段。(ps: map的时候也可以设置不分析)

0. 查看一个text的分析

  • 在kibana里面的devtool里面执行即可
POST _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
标准分词器分词

1. 精准匹配

属性 查询之key分词的查询json 查询之key不分词的查询json
es中数据 => 分词 { "query": { "match": { "key": "value" } } } { "query": { "term": { "key": "value" } } }
es中数据 => 不分词 { "query": { "match": { "key.keyword": "value" } } } { "query": { "term": { "key.keyword": "value" } } }

2. 模糊匹配 —— 字符串 Levenshtein distance =》 fuzzy

fuzzy匹配是根据 Levenshtein distance 来判断是否匹配,一般长度为 0,1,2 太大将不会匹配,因为结果太多了

  • eg: cat,kat,他们就一个字符不同所以 Levenshtein distance("kat","cat") = 1
属性 fuzzy的key的查询json
es中数据 => 分词 { "query": { "fuzzy": { "key": { "value": "cat" "fuzziness": "1" } } } }
es中数据 => 不分词 { "query": { "fuzzy": { "key.keyword": { "value": "cat" "fuzziness": "1" } } } }

3. 模糊匹配 —— 使用通配符 wildcard 匹配 =》 WildCard

WildCard 匹配 就很像我们SQL里面的like匹配 只不过这里使用 *或者? 来匹配

  • eg: kiy, kity, kimchy 加入要匹配这三个
属性 fuzzy的key的查询json
es中数据 => 分词 { "query": { "wildcard": { "key": { "value": "ki*y" } } } }
es中数据 => 不分词 { "query": { "wildcard": { "key.keyword": { "value": "ki*y" } } } }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容