Elasticsearch-核心篇(6)-高级文档查询

·  阅读 810

一、前置查询数据

POST /student/_doc/1001
{
	"name": "zhangsan",
	"nickname": "zhangsan",
	"sex": "男",
	"age": 30
}

POST /student/_doc/1002
{
	"name": "lisi",
	"nickname": "lisi",
	"sex": "男",
	"age": 20
}

POST /student/_doc/1003
{
	"name": "wangwu",
	"nickname": "wangwu",
	"sex": "女",
	"age": 40
}

POST /student/_doc/1004
{
	"name": "zhangsan1",
	"nickname": "zhangsan1",
	"sex": "女",
	"age": 50
}

POST /student/_doc/1005
{
	"name": "zhangsan2",
	"nickname": "zhangsan2",
	"sex": "女",
	"age": 30
}
复制代码

二、高级查询示例

2.1 查询全部

  1. 可以通过以下两种方式查询所有数据
    • 下面两种查询完全等价
    • query:这里的query代表一个查询对象,里面可以有不同的查询属性
      • match_all:匹配所有
      • match:分词单个匹配
      • term:全词单个匹配
      • terms:全词多个匹配
      • bool:组合查询
      • range:范围查询
      • aggs:聚合查询
    • query可以理解为SQL里面的where
GET student/_search

GET student/_search
{
  "query": {
    "match_all": {}
  }
}
复制代码
  • 返回结果
{
  "took【查询花费时间,单位毫秒】" : 0,
  "timed_out【是否超时】" : false,
  "_shards【分片信息】" : {
    "total【总数】" : 1,
    "successful【成功】" : 1,
    "skipped【忽略】" : 0,
    "failed【失败】" : 0
  },
  "hits"【搜索命中结果】 : {
    "total"【搜索条件匹配的文档总数】 : {
      "value" 【总命中计数的值】: 5,
      "relation"【计数规则】 : "eq" # eq 表示计数准确, gte表示计数不准确
    },
    "max_score" 匹配度分值】: 1.0,
    "hits"【命中结果集合】: [
      ...
    ]
  }
}
复制代码

2.2 匹配查询

  1. match匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系
  2. 指定query的查询模式为match,返回结果和上述一致
GET student/_search
{
  "query": {
    "match": {
      "nickname": "zhangsan"
    }
  }
}
复制代码

2.3 字段匹配查询

  1. multi_match与match类似,不同的是它可以在多个字段中查询
  2. 指定query的查询模式为,multi_match,然后分别指定query和fields
    • query:查询的值
    • fields:可以用来查询匹配列
GET student/_search
{
  "query": {
    "multi_match": {
      "query": "zhangsan", 
      "fields": ["name", "nickname"]
    }
  }
}
复制代码

2.4 关键字精确查询

  1. term查询,精确的关键词匹配查询,不对查询条件进行分词
  2. 以下两种方式效果一致
GET student/_search
{
  "query": {
    "term": {
      "nickname": "zhangsan"
    }
  }
}

GET student/_search
{
  "query": {
    "term": {
      "nickname": {
        "value": "zhangsan"
      }
    }
  }
}
复制代码

2.5 多关键字精确查询

  1. terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件
GET student/_search
{
  "query": {
    "terms": {
      "nickname": ["zhangsan", "zhangsan1"]
    }
  }
}
复制代码

2.6 指定查询字段

  1. 默认情况下,Elasticsearch在搜索的结果中,会把文档中保存在_source的所有字段都返回
  2. 如果只想获取其中的部分字段,可以添加_source的过滤
    • 只返回name和nickname字段
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["name", "nickname"]
}
复制代码

2.7 过滤字段

  1. 除了可以使用_source指定返回字段,也可以通过在_source中指定包含字段和排除字段
    • includes:来指定想要显示的字段
    • excludes:来指定不想要显示的字段
  2. 指定包含字段
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "_source": {
    "includes": "name"
  }
}
复制代码
  1. 排除包含字段
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "_source": {
    "excludes": "name"
  }
}
复制代码

2.8 组合查询

  1. bool把各种其它查询通过must(必须 )、must_not(必须不)、should(应该)的方式进行组合
  2. must:字段必须相等,相当于等于
    • age == 30 && sex == "男"
GET student/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "30"
          }
        },
        {
          "match": {
            "sex": "男"
          }
        }
      ]
    }
  }
}
复制代码
  1. must_not:字段必须不相等,相等于不等于
    • age != 30 && sex != "男"
GET student/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "age": "30"
          }
        },
        {
          "match": {
            "sex": "男"
          }
        }
      ]
    }
  }
}
复制代码
  1. should:相当或
    • age == 30 || sex == "男"
GET student/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "age": "30"
          }
        },
        {
          "match": {
            "sex": "男"
          }
        }
      ]
    }
  }
}
复制代码
  1. 多条件查询
    • age == 30 && nickname != "zhangsan" || sex == "男"
GET student/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "30"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "nickname": "zhangsan"
          }
        }
      ],
      "should": [
        {
          "match": {
            "sex": "男"
          }
        }
      ]
    }
  }
}
复制代码

2.9 范围查询

  1. range 查询找出那些落在指定区间内的数字或者时间,range查询允许以下字符
操作符说明
gt大于>
gte大于等于>=
lt小于<
lte小于等于<=
  1. 查询年龄大于等于10且小于等于20的学生
GET student/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}
复制代码

2.10 模糊查询

  1. 返回包含与搜索字词相似的字词的文档
  2. 编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数,这些更改可以包括
    • 更改字符(box → fox)
    • 删除字符(black → lack)
    • 插入字符(sic → sick)
    • 转置两个相邻字符(act → cat)
  3. 为了找到相似的术语,fuzzy查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展,然后查询返回每个扩展的完全匹配
  4. 通过fuzziness修改编辑距离,一般使用默认值AUTO,根据术语的长度生成编辑距离
    • zhagnsan可以正常查询出zhangsan
GET student/_search
{
  "query": {
    "fuzzy": {
      "nickname": {
        "value": "zhagnsan"
      }
    }
  }
}
复制代码
  1. 指定编辑距离1表示上面的四种替换可以有一个字符发生,例如设置0后上面的查询将查询不到数据
GET student/_search
{
  "query": {
    "fuzzy": {
      "nickname": {
        "value": "zhagnsan",
        "fuzziness": 1
      }
    }
  }
}
复制代码

2.11 单字段排序

  1. sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式,desc降序,asc升序
    • 按照年龄降序排序
    • 注意sort和query同级,相当于SQL的order by和select同级
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}
复制代码

2.12 多字段排序

  1. 假定想要结合使用 age和_score进行查询,并且匹配的结果首先按照年龄排序,然后按照相关性得分排序
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    },
    {
      "_score": {
        "order": "desc"
      }
    }
  ]
}
复制代码

三、高亮查询

  1. 在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮
  2. Elasticsearch可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置
  3. 在使用match查询的同时,加上一个highlight属性,返回时也会携带highlight值,其中高亮的词语在其中
    • pre_tags:前置标签
    • post_tags:后置标签
    • fields:需要高亮的字段
    • title:这里声明title字段需要高亮,后面可以为这个字段设置特有配置,也可以空
  4. 针对nickname做高亮显示
GET student/_search
{
  "query": {
    "match": {
      "nickname": "zhangsan"
    }
  },
  "highlight": {
    "pre_tags": "<font color='red'>",
    "post_tags": "</font>",
    "fields": {
      "nickname": {}
    }
  }
}
复制代码
  • 返回结果,注意观察highlight返回字段,前后拼接上了pre_tags和post_tags
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.3862942,
    "hits" : [
      {
        "_index" : "student",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.3862942,
        "_source" : {
          "name" : "zhangsan",
          "nickname" : "zhangsan",
          "sex" : "男",
          "age" : 30
        },
        "highlight" : {
          "nickname" : [
            "<font color='red'>zhangsan</font>"
          ]
        }
      }
    ]
  }
}
复制代码

四、分页查询

  1. Elasticsearch中查询可以进行分页
    • from:当前页的起始索引,默认从0开始, from = (pageNum - 1) * size,页数从第一页开始
    • size:每页显示多少条
    • 和query同级,相当于MySQL中的limit和select同级
  2. 查询第一页的前两条
GET student/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 2
}
复制代码

五、聚合查询

  1. 聚合允许使用者对es文档进行统计分析,类似与关系型数据库中的group by,当然还有很多其他的聚合,例如取最大值、平均值等等
  2. 聚合查询的结果不受size大小限制,但是受到总查询结果的限制
  3. stats聚合,对某个字段一次性返回count,max,min,avg和sum五个指标
    • stats_aggs:聚合名称,任意
    • stats:聚合种类,其中指定需要聚合字段
GET student/_search
{
  "aggs": {
    "stats_aggs": {
      "stats": {
        "field": "age"
      }
    }
  }
}
复制代码
  • 查询结果
{
  ....,
	"aggregations" : {
    "stats_aggs" : {
      "count" : 5,
      "min" : 20.0,
      "max" : 50.0,
      "avg" : 34.0,
      "sum" : 170.0
    }
  }
}
复制代码
  1. count,max,min,avg和sum
    • 只需要把stats_aggs改一下名字然后stats替换为上面的5中聚合就可以分别得到对应的聚合操作
      • 除了count需要替换为value_count
    • 例如聚合计数和平均计数
GET student/_search
{
  "aggs": {
    "age_aggs": {
      "avg": {
        "field": "age"
      }
    }
  }
}

GET student/_search
{
  "aggs": {
    "min_aggs": {
      "min": {
        "field": "age"
      }
    }
  }
}

GET student/_search
{
  "aggs": {
    "max_aggs": {
      "max": {
        "field": "age"
      }
    }
  }
}

GET student/_search
{
  "aggs": {
    "sum_aggs": {
      "sum": {
        "field": "age"
      }
    }
  }
}

GET student/_search
{
  "aggs": {
    "count_aggs": {
      "value_count": {
        "field": "age"
      }
    }
  }
}
复制代码

六、桶聚合查询

6.1 terms分组统计

  1. 桶聚和相当于sql中的group by语句
GET student/_search
{
  "aggs": {
    "terms_aggs": {
      "terms": {
        "field": "age"
      }
    }
  },
  "size": 0
}
复制代码
  • 注意此处统计的是全部数据,size只是影响返回的命中数据
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "terms_aggs" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 30,
          "doc_count" : 2
        },
        {
          "key" : 20,
          "doc_count" : 1
        },
        {
          "key" : 40,
          "doc_count" : 1
        },
        {
          "key" : 50,
          "doc_count" : 1
        }
      ]
    }
  }
}
复制代码

6.2 terms分组后聚合

  • 聚合里面和其再进行aggs
GET student/_search
{
  "aggs": {
    "terms_aggs": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "avg_agg": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  },
  "size": 0
}
复制代码
  • size只是影响返回命中数据
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "terms_aggs" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 30,
          "doc_count" : 2,
          "avg_agg" : {
            "value" : 30.0
          }
        },
        {
          "key" : 20,
          "doc_count" : 1,
          "avg_agg" : {
            "value" : 20.0
          }
        },
        {
          "key" : 40,
          "doc_count" : 1,
          "avg_agg" : {
            "value" : 40.0
          }
        },
        {
          "key" : 50,
          "doc_count" : 1,
          "avg_agg" : {
            "value" : 50.0
          }
        }
      ]
    }
  }
}
复制代码
分类:
后端