elasticsearch 查询

2020-10-23  本文已影响0人  ClownFreeMan

前言

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

目录

一、建立索引,准备数据

字段名 字段含义 类型 是否能被索引
studentNo 学号 keyword
name 姓名 keyword
sex 性别 keyword
age 年龄 integer
birthday 出生年月 date
address 家庭住址 text
classNo 班级 keyword
isLeader 是否为班干部 boolean
interests 兴趣描述 text

一些常用的查询

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": ".*湖.*"
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读