美文网首页
elasticsearch 查询

elasticsearch 查询

作者: ClownFreeMan | 来源:发表于2020-10-23 14:48 被阅读0次

    前言

    单独写一期关于查询的内容。主要是因为es的数据检索几乎是最重要的部分,也因为这一块的文档资料有限、可参考的例子也不多,查询的语法规则也不像 SQL语句那样具有公认的标准化的语法。就不容易入手。

    目录

    • 1、建立索引、准备一些测试的数据
    • 2、查询API 的说明
    • 3、Query 查询
    • 4、FIlter 查询
    • 5、更多的例子

    一、建立索引,准备数据

    字段名 字段含义 类型 是否能被索引
    studentNo 学号 keyword
    name 姓名 keyword
    sex 性别 keyword
    age 年龄 integer
    birthday 出生年月 date
    address 家庭住址 text
    classNo 班级 keyword
    isLeader 是否为班干部 boolean
    interests 兴趣描述 text
    • 创建索引,设置_settings和_mapping
      类型说明、参考文档 https://www.elastic.co/guide/en/elasticsearch/reference/7.6/mapping.html#field-datatypes
      可 使用确切的mapping字段描述创建index
      可 向已有的mapping中添加字段
      不可 修改已有的字段的数据类型(会导致已有数据条目的类型不匹配),建议重建索引,数据导过去
      不可 修改已有的字段的数据名称 ,建议新建字段,用alias name的方式
      (后面测试查询中很多关系到keyword和分词的问题,所以在建立索引前一定要考虑清楚数据类型和分词的使用)

    一些常用的查询

    GET /test_student
    GET /test_student/_settings
    GET /test_student/_mapping
    GET /test_student/_count
    GET /test_student/_search
    
    PUT /test_student
    {
      "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 0
      },
      "mappings": {
        "properties": {
          "studentNo": {"type": "keyword"},
          "name": {"type": "keyword" },
          "male": { "type": "keyword"},
          "age": { "type": "integer"},
          "birthday": {"type": "date", "format": "yyyy-MM-dd"},
          "address": { "type": "text"},
          "classNo": {"type": "keyword"},
          "isLeader": {"type": "boolean"},
          "interests":{"type": "text"}
        }
      }
    }
    
    • 插入准备的数据
    studentNo name male age birthday classNo address isLeader interests
    1 刘备 24 1985-02-03 1 湖南省长沙市 true 喜欢打篮球、唱歌
    2 关羽 22 1987-08-23 2 四川省成都市 false 喜欢游泳和跑步,经常撸铁
    3 糜夫人 19 1990-06-12 1 上海市 false 会一点日语,书法很好
    4 张飞 20 1989-07-30 3 北京市 false 经常钓鱼,喜欢打篮球
    5 诸葛亮 18 1992-04-27 2 江苏省南京市 true 喜欢下象棋围棋,偶尔撸铁书法贼溜
    6 孙尚香 16 1994-05-21 3 false cosplay爱好者,精通日语
    7 马超 19 1991-10-20 1 黑龙江省哈尔滨市 false 喜欢高尔夫和马术,偶尔钓鱼
    8 赵云 23 1986-10-26 2 浙江省杭州市 false 马术贼溜, 撸铁大师
    POST /test_student/_doc/
    {
      "studentNo":1,
      "name":"刘备",
      "male":"男",
      "age": 32,
      "birthday":"1988-03-28",
      "address":"湖南省长沙市",
      "classNo":"1",
      "isLeader": true,
      "interests":"喜欢打篮球、唱歌"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":2,
      "name":"关羽",
      "male":"男",
      "age": 30,
      "birthday":"1990-07-18",
      "address":"四川省成都市",
      "classNo":"1",
      "isLeader": false,
      "interests":"喜欢打游泳和跑步,经常撸铁"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":3,
      "name":"糜夫人",
      "male":"女",
      "age": 19,
      "birthday":"2001-11-10",
      "address":"上海市",
      "classNo":"1",
      "isLeader": false,
      "interests":"会一点点日语,书法很好"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":4,
      "name":"张飞",
      "male":"男",
      "age": 20,
      "birthday":"2000-02-08",
      "address":"北京市",
      "classNo":"3",
      "isLeader": false,
      "interests":"经常钓鱼,喜欢打篮球"
      
    }
    
    POST /test_student/_doc/
    {
      "studentNo":5,
      "name":"诸葛亮",
      "male":"男",
      "age": 19,
      "birthday":"2001-09-28",
      "address":"江苏省南京市",
      "classNo":"2",
      "isLeader": true,
      "interests":"喜欢下象棋围棋,偶尔撸铁,书法贼溜"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":6,
      "name":"孙尚香",
      "male":"女",
      "age": 16,
      "birthday":"2004-06-18",
      "address":"湖南省长沙市",
      "classNo":"3",
      "isLeader": false,
      "interests":"cosplay爱好者,精通日语"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":7,
      "name":"马超",
      "male":"男",
      "age": 19,
      "birthday":"2001-03-28",
      "address":"黑龙江哈尔滨",
      "classNo":"1",
      "isLeader": false,
      "interests":"喜欢高尔夫和钓鱼,偶尔钓鱼"
    }
    
    POST /test_student/_doc/
    {
      "studentNo":8,
      "name":"赵云",
      "male":"男",
      "age": 23,
      "birthday":"1997-05-05",
      "address":"浙江杭州市",
      "classNo":"2",
      "isLeader": false,
      "interests":"马术贼溜,撸铁大师"
    }
    
    

    二、查询API 的说明

    (摘抄,感觉查询语法并不友好)
    ES中的查询非常灵活,为用户提供了非常方便而强大的API。个人觉得ES的调用接口设计得非常好,所有接口合理且风格一致,值得好好研究!

    Query和Filter
    ES为用户提供两类查询API,一类是在查询阶段就进行条件过滤的query查询,另一类是在query查询出来的数据基础上再进行过滤的filter查询。这两类查询的区别是:

    query方法会计算查询条件与待查询数据之间的相关性,计算结果写入一个score字段,类似于搜索引擎。filter仅仅做字符串匹配,不会计算相关性,类似于一般的数据查询,所以filter得查询速度比query快。
    filter查询出来的数据会自动被缓存,而query不能。
    query和filter可以单独使用,也可以相互嵌套使用,非常灵活。

    Query查询
    下面的情况下适合使用query查询:

    需要进行全文搜索。
    查询结果依赖于相关性,即需要计算查询串和数据的相关性。

    三、query查询的各种方式

    term/terms查询、range查询、bool查询、prefix查询、wildcard查询、regexp查询。以及广泛的bool嵌套

    #================查询=========================
    POST /test_student/_search
    {
      "query": {"match_all": {}}
    }
    
    POST /test_student/_search
    {
      "query": {"match_all": {}},
      "from": 2,
      "size": 5,
      "sort": 
        {
          "classNo": {"order": "asc"}, 
          "birthday": {"order": "desc"}
        }
    }
    
    # term 精确查询,对未分词的字段 匹配值
    POST /test_student/_search
    {
      "query": {
        "term": {
          "name": {
            "value": "诸葛亮"
          }
        }
      } 
    }
    
    POST /test_student/_search
    {
      "query": {
        "term": {
          "name": "诸葛亮"
        }
      }
    }
    
    POST /test_student/_search
    {
      "query": {
        "terms": {
          "name": [
            "诸葛亮",
            "孙尚香"
          ]
        }
      }
    }
    
    POST /test_student/_search
    {
      "query": {
        "terms": {
          "interests": [
            "篮球",
            "撸铁"
          ]
        }
      }
    }
    
    POST /test_student/_search
    {
      "query": {
        "terms": {
          "address": [
            "江苏省南京市",
            "北京市"
          ]
        }
      }
    }
    
    # bool查询 ,主要用于复合查询中,含有三类 ,must ,should, must_not ,决定结果的筛选 必须满足、部分满足条件
    
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "classNo": 3
              }
            },
            {
              "term": {
                "male" : "女"
              }
            }
          ]
        }
      }
    }
    
    # [term] query doesn't support multiple fields ...
    POST /test_student/_search
    {
      "query": {
        "term": {
          "classNo": 3,
          "male":"女"
        }
      }
    }
    
    
    # ids 查询, 查询某个索引下的指定 _id 值(默认是自己生成的那个序号)
    
    POST /test_student/_search
    {
      "query": {
        "ids": {
          "type": "_doc", 
          "values": ["FkkrSnUBlOj8Ks4LAS7U", "F0kzSnUBlOj8Ks4Lri5D"]
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "ids": {
          "values": ["FkkrSnUBlOj8Ks4LAS7U", "F0kzSnUBlOj8Ks4Lri5D"]
        }
      }
    }
    
    
    # prefix 前缀匹配
    POST /test_student/_search
    {
      "query": {
        "prefix": {
          "name": {
            "value": "赵"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "prefix": {
                "name": "刘"
              }
            },
            {
              "prefix": {
                "name": "关"
              }
            },
            {
              "prefix": {
                "name": "张"
              }
            },
            {
              "prefix": {
                "name": {
                  "value": "诸葛"
                }
              }
            }
          ]
        }
      }
    }
    
    POST /test_student/_search
    {
      "query": {
        "prefix": {
          "address": {
            "value": "湖"
          }
        }
      }
    }
    # 不清楚为什么 text类型的数据 前缀匹配,中文只能匹配一个字
    # keyword 类型就能匹配多个字, 也许和分词器有关系
    POST /test_student/_search
    {
      "query": {
        "prefix": {
          "address": {
            "value": "湖南"
          }
        }
      }
    }
    
    
    # range 查询, 查找范围值
    POST /test_student/_search
    {
      "query": {
        "range": {
          "age": {
            "gte": 20,
            "lte": 24
          }
        }
      },
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        }
      ]
    }
    
    POST /test_student/_search
    {
      "query": {
        "range": {
          "birthday": {
            "gte": "1995-01-01",
            "lte": "2002-01-01"
          }
        }
      },
      "sort": 
        {
          "age": {"order": "asc" },
          "classNo": {"order": "asc" }
        }
    }
    
    # Wildcard 简化的正则查询, 使用两个通配符 * 代表任意(包括0个)多个字符 ? 代表任意一个字符
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "name": {
            "value": "*亮"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "name": {
            "value": "诸葛*"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "name": {
            "value": "诸葛*"
          }
        }
      }
    }
    
    # text 类型的对字符串的前后缀匹配都不怎么好事, 默认分词器 分成了全部单一的汉字
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "interests": {
            "value": "*铁*"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "interests": {
            "value": "*撸铁*"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "name": "???"
        }
      }
    }
    
    
    # regx 正则查询,最完整的串匹配规则
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": "湖南*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": "湖南省*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": "*长沙*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": "*长*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "interests": "cosplay*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "interests": "cosplay*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "interests": "cos*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "interests": "c*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "name": "孙*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "name": "孙尚*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "name": "孙尚香*"
        }
      }
    }
    
    
    # 关于 filter 的查询, 把上面query 换成filter就行 ,不重复写了,可以附带_cache 来提高效率
    
    

    五、更多的例子

    
    # 更多的例子####################################
    # 查询年龄大于二十的人
    # 查询年龄大于二十的男性
    # 查询三班的男生
    # 查询小于20岁的领导
    # 查询名字只有两个字的人
    # 查询兴趣包含撸铁的人
    # 查询兴趣包含撸铁和跑步的人
    # 查询兴趣包含撸铁或跑步的人
    # 查询住址 符合××省××市的格式的人
    # 查询住址在湖南的人
    
    POST /test_student/_search
    {
      "query": {
        "range": {
          "age": {
            "gte": 20,
            "lte": 100
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "age": {
                  "gte": 20,
                  "lte": 100
                }
              }
            },
            {
              "term": {
                "male": "男"
              }
            }
          ]
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "term":{
                "classNo": 3
              }
            },
            {
              "term": {
                "male": "男"
              }
            }
          ]
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "age": {
                  "gte": 0,
                  "lte": 20
                }
              }
            },
            {
              "term": {
                "isLeader": true
              }
            }
          ]
        }
      }
    }
    POST /test_student/_search
    {
      "query":{
        "wildcard": {
          "name": {
            "value": "??"
          }
        }
      }
    }
    # 分词器的原因, 撸铁查不到
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "interests": {
            "value": "*撸*"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "wildcard": {
                "interests": {
                  "value": "*撸*"
                }
              }
            },
            {
              "wildcard": {
                "interests": {
                  "value": "*跑*"
                }
              }
            }
          ]
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "interests": {
                  "value": "*撸*"
                }
              }
            },
            {
              "wildcard": {
                "interests": {
                  "value": "*跑*"
                }
              }
            }
          ]
        }
      }
    }
    # 分词器的原因,查不出来, 需要使用bool嵌套(一度怀疑分词器有什么破用处。。。)
    POST /test_student/_search
    {
      "query": {
        "wildcard": {
          "address": {
            "value": "*省*市"
          }
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "wildcard": {
                "address": {
                  "value": "*省*"
                }
              }
            },
            {
              "wildcard": {
                "address": {
                  "value": "*市"
                }
              }
            }
          ]
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": ".*湖南.*"
        }
      }
    }
    POST /test_student/_search
    {
      "query": {
        "regexp": {
          "address": ".*湖.*"
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:elasticsearch 查询

          本文链接:https://www.haomeiwen.com/subject/cissmktx.html