《ElasticStack从入门到实践》学习笔记4

四、ElasticSearch的Search API

    0、在ES中,为了实现对存储的数据进行查询分析,使用endpoint:_search

        可以实现对索引的不同查询,如:

        A、实现对所有索引的泛查询:GET /_search

        B、实现对一个索引的单独查询:GET /my_index/_search

        C、实现对多个索引的指定查询:GET /my_index1,my_index2/_search

        D、实现对符合指定要求的索引进行查询:GET /my_*/_search

        在进行查询的时候,主要有两种方式:

        A)URI Search。

            特点:操作简单,直接通过命令行方便测试,但仅包含部分查询语法;

            举例:

#URI Search方式进行查询
GET /my_index/_search?q=username:alfred

        B)Request Body Search。

            特点:ES提供的完备查询语法,使用Query DSL(Domain Specific Language)进行查询。

            举例:

Request Body Search方式进行查询
GET /my_index/_search
{
 "query":{
  "match":{
   "username":"alfred"
  }
 }
}

    1、URI Search:

        1)通过url query参数实现搜索,常用参数有:

            A、q                            指定查询的语句,使用query string syntax语法

            B、df                           q中不指定字段时默认查询的字段    ===>   在不指定的时候默认查询所有字段

            C、sort                       排序

            D、timeout                 指定超时时间,默认不超时   

            E、from,size            用于分页

        举例:

#使用url query查询示例:
GET my_index/_search?q=alfred&df=username&sort=age:asc&from=4&size=10&timeout=1s

        解释:

        查询索引my_indexusername字段中包含alfred的文档,结果按age字段升序排列,返回第5——14个文档,若超过1s未结束,则以超时结束。

        2)query string syntax语法

            前置内容:term————单词,phrase————词语。

            A、单词与词语语法:

                单词:alfred way    等价于    alfred OR way

                词语:"alfred way"    语句查询,要求先后顺序

                泛查询:不指定字段,会在所有字段中去匹配其单词

                指定字段查询:指定字段,在指定字段中匹配单词

            B、Group分组设定,使用括号指定匹配的规则,举例:

#分组设定,使用括号进行分组
GET my_index/_search?q=username:(alfred OR way)AND lee

        3)search api

            A、泛查询:

#泛查询
GET my_index/_search?q=alfred
{
 "profile":true    #使用profile参数,可以明确地看到ES如何执行的查询条件
}

            B、指定字段查询:

                    a、查询字段username中包含alfred的文档:

#查询字段username中包含alfred的文档
GET my_index/_search?q=username:alfred

                    b、查询字段username中包含alfred或way的文档

#查询字段username中包含alfred或way的文档
GET my_index/_search?q=username:alfred way

                    c、查询字段username为"alfred way"的文档

#查询字段username为"alfred way"的文档
GET my_index/_search?q=username:"alfred way"

                    d、分组后,查询字段username中包含alfred和包含way的文档

#分组后,查询字段username中包含alfred,包含way的文档
GET my_index/_search?q=username:(alfred way)

                    这个和b的结果一样,但是区别在于使用分组之后,不进行泛查询。

        4)布尔操作符

            A、AND(&&)、OR(||)、NOT(!),举例:

#查询索引my_index中username包含alfred但是不包含way的文档
GET my_index/_search?q=username:(alfred NOT way)

            B、+对应must,-对应must_not,举例:

#查询索引my_index中一定包含lee,一定不含alfred,可能有way的文档
GET my_index/_search?q=username:(way +lee -alfred)
#或写成
GET my_index/_search?q=username:((lee && !alfred) || (way && lee && !alfred))

            但是要注意一点:

            在url中,+(加号)会被解析成空格,所以要使用encode后的结果,即:%2B,所以正确的查询语句应该为:

#查询索引my_index中一定包含lee,一定不包含alfred,可能包含way的文档
GET my_index/_search?q=username:(way %2Blee -alfred)

        5)范围查询(支持数值和日期)

            A、区间写法:闭区间使用[ ],开区间使用{ }

                a、age:[1 TO 10]                                1 <= age <= 10

                b、age:[1 TO 10}                                1 <= age < 10

                c、age:[1 TO ]                                     age >= 1

                d、age:[* TO 10]                                age <= 10

            B、算数符号写法:

                a、age:>= 1                                        

                b、age:(>=1 && <= 10) / age:(+ >= 1 + <= 10)

                举例:

#查询索引my_index中username字段包含alfred或年龄大于20的文档
GET my_index/_search?q=username:alfred age>20

#查询索引my_index中username字段包含alfred且年龄大于20的文档
GET my_index/_search?q=username:alfred AND age>20

            C、还可以对日期进行范围查询,注意:年/月是从1月1号/1号开始算的:

#查询索引my_index中birth字段在1985和1990之间的文档
GET my_index/_search?q=birth:(>1985 AND < 1990)

        6)通配符查询

            ?代表一个字符,*代表0个或多个字符,如:

            name:a?lfred         /         name:a*d         /        name:alfred*

            注意:通配符匹配的执行效率较低,且占用内存较多,不建议使用,如果没有特殊要求,也不要将?或者*放在最前面,因为意味着要匹配所有文档,可能会造成OOM。

        7)此外,还支持正则表达式/模糊匹配/近似度查询等

            A、正则表达式:举例:/[a]?l.*/

            B、模糊匹配:fuzzy query。举例:

#模糊匹配。匹配与alfred差一个字符的词,比如:alfreds、alfret等
GET my_index/_search?q=username:alfred~1

            C、近似度查询:proximity search。举例:

#近似度查询,查询字段username和"alfred way"差n个单词的文档
GET my_index/_search?q=username:"alfred way" ~5

            使用场景常见于用户输入词的纠错中。

    2、Request Body Search

        ES自带的完备查询语句,将查询语句通过http request body发送到ES,主要参数有:

        ①query    ===>    符合Query DSL语法的查询条件

        ②from,size

        ③timeout

        ④sort

        Query DSL语法:

        基于JSON定义的查询语言,主要包含两个类型:

        1)字段类查询————如:term,match,range等。只针对一个字段进行查询

                A、全文匹配

                    针对text类型的字段进行全文检索,会对查询语句进行“先分词再查询”处理,如:match、match_phrase等

                    a、match query

                       ①对字段进行全文检索(最基本和最常用的查询类型),举例:

#match query
GET my_index/_search
{
  "query":{  
   "match":{    #关键词
    "username":"alfred way"    #字段名和查询语句
   }
  }
}

                       从结果,可以返回匹配文件总数,返回文档列表,_score相关性得分等。

                       一般的执行流程为:

            1.对查询语句分词==>2.根据字段的倒排索引列表,进行匹配算分==>3.汇总得分==>4.根据得分排序,返回匹配文档

                       ②使用operator参数,可以控制单词间关系,有and / or:

#使用operator参数控制单词间关系
GET my_index/_search
{
 "query":{
  "match":{
   "username":"alfred way",
   "operator":"and"    #and,同时包含alfred和way
  }
 }
}

                       ③使用minimum_should_match参数控制需匹配的单词数

#使用minimum_should_match参数控制需匹配的单词数
GET my_index/_search
{
 "query":{
  "match":{
   "username":"alfred way",
   "minimum_should_match":"2"
  }
 }
}

                    b、相关性算分,其本质就是一个排序问题

                        计算文档与待查询语句之间的相关度,一般有四个重要概念:

                        a、Term Frequency 词频(正相关)

                        b、Document Frequency 文档频率(负相关)

                        c、Inverse Term Frequency 逆文本频率(正相关)

                        d、Field-length Norm 文档长度(负相关)

                        目前ES有两个相关性算分的模型:

                        ①TF/IDF模型。经典模型。

                        在使用kibana进行查询时,使用explain参数,可以查看具体的计算方法。

#使用explain参数,可以查看具体的相关性的得分是如何计算的
GET my_index/_search
{
 "explain":true,    #设置为true
 "query":{
  "match":{
   "username":"alfred"
  }
 }
}

                        注意:ES计算相关性得分是根据shard进行的,即分片的分数计算相互独立,所以在使用的时候要注意分片数,可以通过设定分片数为1来避免这个问题,主要是为了观察,不代表之后所有的分片全都设为1。一般放在创建索引后,未加数据之前。

#设定shards数量为1
PUT my_index
{
 "settings":{
  "number_of_shards":"1"
 }
}

                        ②BM25模型。5.x版本后的默认模型,是对TF/IDF的优化模型。best match,25指:迭代了25次才计算。

                        BM25的使用,降低了TF/IDF中因为TF过大导致的负面影响,在BM25中,一个单词的TF一直增长,到一定程度就趋于0变化。

                    c、match phrase query

                        对字段做全文检索,有顺序要求。

#使用match——phrase查询词语
GET my_index/_search
{
 "query":{
  "match_phrase":{    #关键词
   "job":"java engineer"
  }
 }
}

                        通过使用slop参数,可以控制单词间间隔:

#使用slop参数,控制词语中的单词间隔
GET my_index/_search
{
 "query":{
  "match_phrase":{
   "job":{
    "query":"java engineer",
    "slop":"1"    #关键词,设定单词间隔
   }
  }
 }
}

                    d、query string query

                        类似于URI Search中的q参数查询,举例:

#使用query_string查询
GET my_index/_search
{
 "query":{
  "query_string":{
   "default_field":"username",
   "query":{alfred AND way"
  }
 }
}
#或
GET my_index/_search
{
 "query":{
  "query_string":{
   "fileds":["username","job"],
   "query":"alfred OR (java AND ruby)"
  }
 }
}

                    e、simple query string query

                        类似于query string,但会忽略错误的查询语法,且仅支持部分查询语句。使用+,|,-分别代替AND,OR,NOT。

                举例:

#使用simple query string query
GET my_index/_search
{
 "query":{
  "simple_query_string":{
   "fields":[username],
   "query":"alfred +way"    #等价于 "query":"alfred AND way"
  }
 }
}

                B、单词匹配

                    a、term/terms query

                        将待查询语句作为整个单词进行查询,不做分词处理,举例:

#使用term进行单查询
GET my_index/_search
{
 "query":{
  "term":{
   "username":"alfred"
  }
 }
}
#使用terms进行多查询
GET my_index/_search
{
 "query":{
  "terms":{
   "username":["alfred","way"]
  }
 }
}

                        此时如果直接使用alfred way作为username查询条件,是不会返回任何文档的。因为在username的倒排索引列表中,存在"alfred"和"way"的索引,但是不存在"alfred way"的索引。

                    b、range query

                        范围查询,主要针对数值类型和日期类型。

                        gt: greater than 大于

                        gte: greate than or equal to 大于等于

                        lt: less than 小于

                        lte: less than or equal to 小于等于

                        ①对数值的查询

#range query对数值的查询
GET my_index/_search
{
 "query":{
  "range":{
   "age":{
    "gte":10,
    "lte":20
   }
  }
 }
}

                        ②对日期的查询

#range query对日期的查询
GET my_index/_search
{
 "query":{
  "range":{
   "birth":{
    "lte":"1988-01-01"   #或者使用  "lte":"now-30y",这种Date Math类型
   }
  }
 }
}

                        Date Math类型:针对日期提供的一种更友好的计算方式。

                        当前时间用now代替,具体时间的引用,需要使用||间隔。年、月、日、时、分、秒跟date一致:y、M、w、d、h、m、s。举例:

#假设当前时间为2018-01-02 12:00:00
now+1h   =>   2018-01-02 13:00:00
now-1h   =>   2018-01-02 11:00:00
now-1h/d =>   2018-01-02 00:00:00
2016-01-01||+1M/d  => 2016-02-01 00:00:00

                    2)复合查询————如:bool查询等。包含一个/多个字段类查询/符合查询语句

                A、constant_score query

                    将内部的查询结果文档得分全部设定为1或boost的值。返回的相关性得分全部为1或boost

#使用constant_score query
GET my_index/_Search
{
 "query":{
  "constant_score":{    #关键词
   "match":{
    "username":"alfred"
   }
  }
 }
}

                B、bool query

                    由一个/多个布尔子句组成,主要包含以下四个:

                    a、filter                     只过滤符合条件的文档,不计算相关性得分,返回的相关性得分全部为0;

                        ES会对filter进行智能缓存,因此执行效率较高,在做简单匹配查询且不考虑得分的时候没推荐使用filter代替query

#使用filter查询
GET my_index/_search
{
 "query":{
  "bool":{    #关键词
   "filter":[
    "term":{
     "username":"alfred"
    }
   ]
  }
 }
}

                    b、must                    文档必须符合must中的所有条件,影响相关性得分;

                       

#使用must进行查询
GET my_index/_search
{
 "query":{
  "bool":{
   "must":[    
    {
     "match":{
      "username":"alfred"
     }
    },
    {
     "match":{
      "job":"specialist"
     }
    }
   ]
  }
 }
}

                    c、must_not             文档必须排除must_not中的所有条件; 

#使用must_not进行查询
GET my_index/_search
{
 "query":{
  "bool":{
   "must":[
   {
    "match":{
     "job":"java"
    }
   }
   ],
   "must_not":[
   {
    "match":{
     "job":"ruby"
    }
   }
   ]
  }
 }
}

                    d、should                 文档可以符合should中的条件,影响相关性得分,分为两种情况:

                       同时配合minimum_should_match控制满足调价你的个数/百分比。

                       ①bool查询中只有should,不包含must的情况

                           

#bool查询中只有should的情况
GET my_index/_search
{
 "query":{
  "bool":{
   "should":[
    {
     "term":{"job":"java"}    #条件1
    },
    {
     "term":{"job":"ruby"}    #条件3
    }
    {
     "term":{"job":"specialist"}    #条件3
    }
   ],
   "minimum_should_match":2    #至少需要满足两个条件
  }
 }
}

                       ②bool查询中既有should,又包含must的情况,文档不必满足should中的条件,但是如果满足的话则会增加相关性得分。

#bool查询中同时包含should和must
GET my_index/_search
{
 "query":{
  "bool":{
   "should":[    #同时包含should
   {
    "term":{"job":"ruby"}
   }
   ],
   "must":[    #同时包含must
   {
    "term":{"usernmae":"alfred"}
   }
   ]
  }
 }
}

                当一个查询语句位于query或filter上下文的时候,ES的执行结果也不同。

query查找和查询语句最匹配的文档,并对所有文档计算相关性得分query
bool中的:must/should
filter查找和查询语句最匹配的文档bool中的:filter/must_not
constant_score中的:filter

 

#query和filter上下文
GET my_index/_search
{
 "query":{
  "bool":{
   "must":[    #query上下文
   {
    "term":{"title":"Search"}
   },
   {
    "term":{"content":"ElasticSearch"}
   }
   ],
   "filter":[    #filter上下文
   {
    "term":{"status":"published"}
   },
   {
    "range":{
     "publish_date":{
      "gte":"2015-01-01"
     }
    }
   }
   ]
  }
 }
}

                D、count API

                获取符合条件的文档书,使用endpoint:_count。

#使用_count获取符合条件的文档数
GET my_index/_count    #关键词
{
 "query":{
  "match":{
   "username":"alfred"
  }
 }
}

                E、Source Filtering

                过滤返回结果中的_source中的字段,主要由以下两种方式:

                    a、GET my_index/_search?_source=username        #url参数

                    b、使用Request Body Search:

#不返回_source
GET my_index/_search
{
 "_source":false
}
#返回_source部分字段
GET my_index/_search
{
 "_source":["username","age"]
}
#通配符匹配返回_source部分字段
GET my_index/_search
{
 "_source":{
  "includes":"*I*",
  "encludes":"birth"
 }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值