zoukankan      html  css  js  c++  java
  • Elastic Search快速上手(3):搜索

    前言

    存储好数据之后,便可通过RESTful API进行搜索。

    详细文档可参考:
    --简单搜索https://www.elastic.co/guide/cn/elasticsearch/guide/cn/search.html
    --深入搜索https://www.elastic.co/guide/cn/elasticsearch/guide/cn/search-in-depth.html

    注:对前文的一个补充,可以使用analyze来查看分词器的分词结果。

    GET _analyze
    {
      "analyzer": "ik_smart",
      "text":"数据结构算法熟悉"
    }
    

    分词结果:

    {
      "tokens": [
        {
          "token": "数据结构",
          "start_offset": 0,
          "end_offset": 4,
          "type": "CN_WORD",
          "position": 0
        },
        {
          "token": "算法",
          "start_offset": 4,
          "end_offset": 6,
          "type": "CN_WORD",
          "position": 1
        },
        {
          "token": "熟悉",
          "start_offset": 6,
          "end_offset": 8,
          "type": "CN_WORD",
          "position": 2
        }
      ]
    }
    

    基本搜索

    请求路径

    搜索使用GET方式,GET请求的路径中,可以包含目标索引、类型和文档 id。

    /_search
    在所有的索引中搜索所有的类型
    /gb/_search
    在 gb 索引中搜索所有的类型
    /gb,us/_search
    在 gb 和 us 索引中搜索所有的文档
    /g*,u*/_search
    在任何以 g 或者 u 开头的索引中搜索所有的类型
    /gb/user/_search
    在 gb 索引中搜索 user 类型
    /gb,us/user,tweet/_search
    在 gb 和 us 索引中搜索 user 和 tweet 类型
    /_all/user,tweet/_search
    在所有的索引中搜索 user 和 tweet 类型
    

    轻量搜索

    可以直接在请求url中,附加搜索关键词。
    例如,查询在 tweet 类型中 tweet 字段包含 elasticsearch 单词的所有文档:
    GET _all/tweet/_search?q=tweet:elasticsearch
    但这种方式当条件较为复杂时,url会很难读。

    请求体查询

    形如:(注,有时GET不支持带请求体,因此这里的GET请求也可换成POST)

    GET _search
    {
        "query": {
            "match_all": {}
        }
    }
    

    match查询

    例如,查找title字段中含有python的:

    GET test/_search
    {
      "query":{
        "match":{
          "title":"python"
        }
      }
    }
    

    返回结果:

    {
      "took": 48, # 耗时48ms
      "timed_out": false, # 未超时
      "_shards": {
        "total": 5, # 共有5个分片进行查询
        "successful": 5, # 5个分片成功查询
        "failed": 0
      },
      "hits": { # 一共有3条满足条件的记录
        "total": 3,
        "max_score": 0.45203948, # 最高得分
        "hits": [ # 以下为结果集
          {
            "_index": "test",
            "_type": "job",
            "_id": "AV3LXb9wdmPltg3H8bEu",
            "_score": 0.45203948,
            "_source": {
              "title": "python打造推荐引擎系统",
              "company_name": "阿里巴巴科技公司",
              "desc": "熟悉推荐引擎的原理以及算法,掌握C语言",
              "comments": 60,
              "add_time": "2016-10-20"
            }
          }#略
          ]
      }
    }
    

    注意

    如果在一个精确字段上面使用match,则会精确匹配,比如在数字或者keyword的字段上使用。如果是text类型,则数据和查询语句都会经过分词器的处理。

    例如,如果标题中为python,而查询词为大写Python,若经过ik分词,都会被转换为小写,因此仍然能查出;但如果此title字段未经分词,而是keyword类型的话,则大小写不匹配,就无法查出。

    此外,match中只能指定一个查询字段。

    term查询

    区别是term对于查询词不会进行分词,必须精确完全匹配。

    GET test/_search
    {
      "query":{
        "term":{
          "title":"python打造"
        }
      }
    }
    

    terms查询

    可指定多个关键词进行term查询,满足其中一个关键词即可。

    GET test/_search
    {
      "query":{
        "terms":{
          "title":["python打造","django"]
        }
      }
    }
    

    match_all查询

    最简单的,查找所有。

    GET test/_search
    {
     "query": {
       "match_all": {}
     }
    }
    

    match_phrase查询

    在match查询中,如果对text字段指定了像“python教程”这样的查询词,会进行分词,包含python或教程的结果都会被查询出来。而match_phrase也会进行分词,但是只有全部包含这些词的结果会被查询出来。

    GET test/_search
    {
      "query":{
        "match_phrase": {
          "title":{
            "query":"python系统",
            "slop":6
          }
        }
      }
    }
    

    slop的含义是拆分出来的词之间的最大间距。若超出此间距,就算都包含这些词,也不会返回。

    multi_match查询

    match查询只能指定一个字段,而multi_match可以指定多个字段。

    GET test/_search
    {
      "query":{
        "multi_match": {
          "query":"python",
          "fields":["title^3","desc"]
        }
      }
    }
    

    上面语句是同时在title和desc中查询python关键词。注意到^3,是指定权重,title字段的权重是desc的三倍。

    查询范围

    查询comments中大于5小于等于60的数据:

    GET test/_search
    {
      "query":{
        "range":{
          "comments":{
            "gt":5,
            "lte":60
          }
        }
      }
    }
    

    查询时间大于17-4-1而且小于等于当前:

    GET test/_search
    {
      "query":{
        "range":{
          "add_time":{
            "gt":"2017-04-01",
            "lte":"now",
            "boost":2.0
          }
        }
      }
    }
    

    (boost是权重,可有可无,别的地方也可以用)

    通配符查询

    查询pyt*n:

    GET test/_search
    {
      "query":{
          "wildcard":{
            "title":{
              "value":"pyt*n",
              "boost":2.0
            }
          }
      }
    }
    

    查询结果分页

    可以进行查询结果的分页,指定从第几个开始,取几个。

    GET test/_search
    {
      "query":{
        "match":{
          "title":"python"
        }
      },
      "from":0,
      "size":2
    }
    

    只返回部分字段

    还是可以通过_source指定返回哪些字段。

    GET test/_search
    {
      "_source": ["title","company_name"], 
      "query":{
        "match":{
          "title":"python"
        }
      }
    }
    

    返回结果排序

    对comments字段按照asc升序排列(desc为降序):

    GET test/_search
    {
      "query":{
        "match":{
          "title":"python"
        }
      },
      "sort":{
        "comments":{
          "order":"asc"
        }
      }
    }
    

    bool查询

    查询参数

    bool查询将多查询组合在一起,它包含以下四种参数:
    must
    文档 必须 匹配这些条件才能被包含进来。
    must_not
    文档 必须不 匹配这些条件才能被包含进来。
    should
    如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
    filter
    必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

    简单过滤

    在bool中可指定filter进行过滤。
    如,使用term精确匹配出salary为20的文档:

    GET test2/job/_search
    {
      "query":{
        "bool":{
          "filter":{
            "term":{
              "salary":20
            }
          }
        }
      }
    }
    

    如果想过滤多个值,可以用terms。

    组合查询

    灵活运用各种组合过滤查询。例如,下面的查询,是{salary不能为30}并且{salary为20 或者 title匹配python}

    GET test2/job/_search
    {
      "query":{
        "bool":{
          "should":[
            {"term":{"salary":20}},
            {"match":{"title":"python"}}
          ],
          "must_not":{
            "term":{"salary":30}
          }
        }
      }
    }
    

    嵌套查询

    bool可进行嵌套。下面的例子,外层should并列两个条件或,要么标题含有python,要么必须满足标题精确匹配django而且salary精确匹配30.

    GET test2/job/_search
    {
      "query":{
        "bool":{
          "should":[
            {"match":{"title":"python"}},
            {"bool":{
              "must":[
                {"term":{"title":"django"}},
                {"term":{"salary":30}}
                ]
            }}
          ]
        }
      }
    }
    

    exists

    用于查询某个字段是否存在或为null。
    下面例子中,前者筛选出存在title字段的文档,后者则反之。

    GET test2/job2/_search
    {
      "query":{
        "bool":{
          "filter":{
            "exists": {
              "field": "title"
            }
          }
        }
      }
    }
    
    GET test2/job2/_search
    {
      "query":{
        "bool":{
          "must_not":{
            "exists": {
              "field": "title"
            }
          }
        }
      }
    }
    


    经过上面的介绍,基本整理了es的搜索中的常用方法,能满足最基础的搜索使用。更详细的搜索,请参阅文档。

  • 相关阅读:
    为什么要用webUI?
    探索WebKit内核(一)------ 菜鸟起步
    主进程退出的时候,杀死所有子进程
    那两年炼就的Android内功修养
    飞鸽---局域网聊天软件攻防战
    如何利用Fluxion诱惑目标用户获取WPA密码
    性能测试:CPU内存,硬盘IO读写,带宽速度,UnixBench
    解决maven编译错误:程序包com.sun.xml.internal.ws.spi不存在
    Apache-Flink深度解析-DataStream-Connectors之Kafka
    linux下find(文件查找)命令的用法总结
  • 原文地址:https://www.cnblogs.com/aaanthony/p/7380707.html
Copyright © 2011-2022 走看看