Elasticsearch查询语法

超时(timeout)

  • 用法: GET /_search?timeout=1s/ms/m (秒/毫秒/分)
  • 设置:默认es没有timeout,如果设置timeout,则执行timeout机制。
  • timeout机制:每个share只能在timeout指定的时间范围内,将搜索到的部分数据(或全部搜索到的数据),直接返回给客户端,而不是待数据全部查询出来之后,再返回给客户端。【指定时间内,取到多少,返回多少】

ES常用查询

  1. query_string

    • 查询指定索引所有: GET /索引名/_search

    • 查询指定所以特定条件数据:

      GET  /索引名/_search?q=字段名称:字段值   如 GET /product/_search?q=name:nfc
      
    • 分页:GET /索引名/_search?from=页码&size=条数&q=字段名称:字段值

  2. query_dsl (英语:domain-specific language、DSL)

    • match_all : 匹配指定索引所有

      GET /product/_search
      {
        "query": {
          "match_all": {}
        }
      }
      
    • match 匹配所有中name字段含有nfc的数据

      GET /product/_search
      {
        "query": {
            "match": {
              "name": "nfc"
            }
        }
      }
      
    • sort 按照价格倒叙排序。一但排序,则_score值为null

      GET /product/_search
      {
        "query": {
            "match_all": {}
        }
        , "sort": [
          {
            "price": {
              "order": "desc"
            }
          }
        ]
      }
      
    • multi_match 根据多个字段查询关键词。name和desc中任何一个字段包含“nfc”的doc

      GET /product/_search
      {
        "query": {
          "multi_match": {
            "query": "nfc",
            "fields": ["name","desc"]
          }
        }
      }
      
    • _source : 指定查询字段。查询name和price字段

      GET /product/_search
      {
        "query": {
          "multi_match": {
            "query": "nfc",
            "fields": ["name","desc"]
          }
        }
        , "_source": ["name","price"]
      }
      
    • 分页 查询第二页,每页两条数据

      GET /product/_search
      {
        "query": {
          "match_all": {}
        }
        , "sort": [
          {
            "price": {
              "order": "desc"
            }
          }
        ]
        , "from": 1
        , "size": 2
      }
      
  3. 全文检索(full-text-query)

    • query-term 不会被分词, 体会term terms 和 match 区别

      GET /product/_search
      {
        "query": {
          "term": {
            "name": {
              "value": "nfc"
            }
          }
        }
      }
      /**
      *  体会与match的区别
      **/
      GET /product/_search
      {
        "query": {
          "term": {
            "name": {
              "value": "nfc phone" // 作为一个分词(整体)与name字段匹配
            }
          }
        }
      }
      
      GET /product/_search
      {
        "query": {
         "match": {
           "name": "nfc phone" // 被分词器分为 nfc 和 phone 两个分词与name字段匹配
         }
        }
      }
      
      // name中必须(must)含有xiaomi 和 nfc 两个条件
      GET /product/_search
      {
        "query": {
          "bool": {
            "must": [
              {"term": {
                "name": {
                  "value": "xiaomi"
                }
              }}
              ,{"term": {
                "name": {
                  "value": "nfc"
                }
              }}
            ]
          }
        }
      }
      // 两个单独的分词“nfc”和“xiaomi” (一定是两个分词) 两个分词与name进行匹配
      GET /product/_search
      {
        "query": {
          "terms": {
            "name": [
              "nfc",
              "xiaomi"
            ]
          }
        }
      }
      // 字符串“nfc iphone” 被分词有在与name配置,是否被分词两个字要看分词器的分词结果。逻辑上“nfc iphone”有可能作为一个整体。
      GET /product/_search
      {
        "query": {
          "match": {
            "name": "nfc iphone"
          }
        }
      }
      
      
      
      
    • 验证分词

      GET /_analyze
      {
        "analyzer": "standard"
        , "text": ["xiaomi nfc zhineng phone"]
      }
      
      分词结果
      {
        "tokens" : [
          {
            "token" : "xiaomi",
            "start_offset" : 0,
            "end_offset" : 6,
            "type" : "<ALPHANUM>",
            "position" : 0
          },
          {
            "token" : "nfc",
            "start_offset" : 7,
            "end_offset" : 10,
            "type" : "<ALPHANUM>",
            "position" : 1
          },
          {
            "token" : "zhineng",
            "start_offset" : 11,
            "end_offset" : 18,
            "type" : "<ALPHANUM>",
            "position" : 2
          },
          {
            "token" : "phone",
            "start_offset" : 19,
            "end_offset" : 24,
            "type" : "<ALPHANUM>",
            "position" : 3
          }
        ]
      }
          
      
  1. 短语搜索(phrase search),和全文搜索相反,

    GET /product/_search
    {
      "query": {
        "match_phrase": {
          "name": "nfc iphone"
        }
      }
    }
    
    1>: name字段会被分词器分词
    2>: 被搜索文本中出现name所有分词后的字段,并且文本内容必须和name分词之后的词出现的顺序一致。 
    

查询和过滤

  1. bool 查询:可以组合多个查询条件,bool查询采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。

    • must :必须满足。 子语句(查询)必须出现在匹配的文档中,相当于sql中and

    • must_not:必须不满足,不计算相关分数。相当于sql中 not。

      子句(查询)不得出现的匹配文档中,子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。

    1. should :可能满足。相当于sql中的or。子句(查询)应出现在匹配的文档中。
    • filter:过滤器,不计算相关度分数,应用cache;

      子句(查询)必须出现在匹配的文档中,但是不行must查询的分数被忽略。filter子句在filter上下文中被执行,意味着计分被忽略,并且子句被考虑用于缓存。

  2. 精彩案例

    • 筛选name包含“xiaomi phone” 并且价格大于1999的数据(不排序),搜索name包含“xiaomi” and desc包含“shouji”

      GET /product/_search
      {
        "query": {
          "bool": {
            "must": [
              {"match": {
                "name": "xiaomi"
              }}
              ,{"match": {
                "desc": "shouji"
              }}
              
            ]
            , "filter": [
              {
                "match_phrase": {
                  "name": "xiaomi phone"
                }
              }
              ,{"range": {
                "price": {
                  "gt": 1999
                }
              }}
            ]
          }  
        }
        
      }
      
  • bool 多条件,name包含“xiaomi”, 不包含“erji”。desc里包不包含“nfc”都可以。价格大于等于2999

    GET /product/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "name": "xiaomi"
            }}
          ]
          , "must_not": [
            {"match": {
              "name": "erji"
            }}
          ]
          ,"should": [
            {"match": {
              "desc": "nfc"
            }}
          ]
          ,"filter": [
            {"range": {
              "price": {
                "gt": 2999
              }
            }}
          ]
        }
      }
    }
    
  1. 嵌套查询

    • minimun_should_match:参数指定should 返回的文档必须匹配的子句的数量或者百分比。should查询条件粗只能在时,如果有别的查询条件,如must、must_not、filter,则默认为0,否则为1。如果为0,则should条件可以一个都不满足,如果为1,则should的两个条件满足任何一个就可以,如果为2,则两个条件必须都满足。

    • GET /product/_search
      {
        "query": {
          "bool": {
            "must": [
              {"match": {
                "name": "nfc"
              }}
            ]
            , "should": [
              {"range": {
                "FIELD": {
                  "gte": 1999
                }
              }}
              ,{
                "range": {
                  "FIELD": {
                    "gte": 3999
                  }
                }
              }
            ]
            ,"minimum_should_match": 1
          }
        }
      }
      
      1>:must 不存在,则 minimum_should_match 默认为1, should 下的range必须生效一个。
      2>:must 存在,则 minimum_should_match 默认为0, should下的range可都不生效,可生效一个或者两个。
      3>:minimum_should_match 设置,以设置的值为准。    
      
  2. 组合查询(compound queries)

    • constant_score 搜索结果忽略词频(TF)对搜索结果排序的影响。将查询语句或者过滤语句包装起来。

    • 检索词词频:检索词在该字段出现的频率。出现频率越高,相关性越高。字段中出现过5次要不只出现1次的相关性高。

    • 想要一台NFC功能的或者小米手机, 但是不要带耳机的。

      GET /product/_search
      {
        "query": {
          "bool": {
            "should": [
              {"term": {
                "name": {
                  "value": "nfc"
                }
              }}
              ,{"term": {
                "name": {
                  "value": "xiaomi"
                }
              }}
            ]
            , "must_not": [
              {"term": {
                "name": {
                  "value": "erji"
                }
              }}
            ]
            , "minimum_should_match": 1
          }
        }
      }
      
    • 搜索一台“xiaoami nfc phone”或者(一台手机或者几个小于等于2999)

      GET /product/_search
      {
        "query": {
          "constant_score": {
            "filter": {
              "bool": {
                "should": [
                  {
                    "match_phrase": {
                      "name": "xiaomi nfc phone"
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "match_phrase": {
                            "name": "phone"
                          }
                        },
                        {
                          "range": {
                            "price": {
                              "gte": 2999
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
                , "minimum_should_match": 1
              }
            },
            "boost": 1.2
          }
        }
      }
      
  • 高亮(hightlight search)

    GET /product/_search
    {
      "query": {
        "match_phrase": {
          "name": "nfc phone"
        }
      }
      , "highlight": {
        "fields": {
          "name": {}
        }
      }
    }
    
  1. deep paging

    • 概念理解:简单来说所,就是搜索的特别深。假如说现在es中有60000条记录,分别存在3个primary shard中,则每个primary shard要存20000条记录。
    • 出现的问题:如果要取第1000页(每页10条)数据,则需要在每个primary shard中取10000条记录,然后合并排序,再返回从10001条开始的10条记录。因为3个primary shard数据的_source的分数不一样,可能某一个primary shard中第一条数据都没有另外一个primary shard中的最后一条分数都高。这样取数据可能不正确。
    • 问题解决:采用scroll query。
    • 性能问题:
      1. 耗费网络带宽:如果搜索过深,各个shard要把数据传送给协调节点(coordinate node),这个过程要有大量数据传递和网络消耗。
      2. 消费内存:各个shard要把数据转送给协调节点(coordinate node),这个传递回来的数据,要被协调节点保存到内存,消耗大量内存。
      3. 消耗cpu:node要把传递回来的数据进行排序,排序过程大量消耗cpu。
    • 注意点:
      1. 当数据超过1w。
      2. 返回结果不要超过1000,500以下为宜。

测试数据样例

PUT /product/_doc/1
{
    "name" : "xiaomi phone",
    "desc" :  "shouji zhong de zhandouji",
    "price" :  3999,
    "tags": [ "xingjiabi", "fashao", "buka" ]
}
PUT /product/_doc/2
{
    "name" : "xiaomi nfc phone",
    "desc" :  "zhichi quangongneng nfc,shouji zhong de jianjiji",
    "price" :  4999,
    "tags": [ "xingjiabi", "fashao", "gongjiaoka" ]
}


PUT /product/_doc/3
{
    "name" : "nfc phone",
    "desc" :  "shouji zhong de hongzhaji",
    "price" :  2999,
    "tags": [ "xingjiabi", "fashao", "menjinka" ]
}

PUT /product/_doc/4
{
    "name" : "xiaomi erji",
    "desc" :  "erji zhong de huangmenji",
    "price" :  999,
    "tags": [ "low", "bufangshui", "yinzhicha" ]
}

PUT /product/_doc/5
{
    "name" : "hongmi erji",
    "desc" :  "erji zhong de kendeji",
    "price" :  399,
    "tags": [ "lowbee", "xuhangduan", "zhiliangx" ]
}

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