复杂条件查询

构建查询

重新添加5条数据

es querystring 查询多个条件_字段

通过 match 来构建查询条件,返回结果与上述一致

GET /user/_doc/_search
{
  "query":{
    "match": {
      "name": "zhangsan"
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.3862942,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.3862942,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

同样是模糊查询

GET /user/_doc/_search
{
  "query":{
    "match": {
      "info": "一顿操作"
    }
  }
}

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.9004039,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.3176721,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        }
      }
    ]
  }
}

这里我们可以看到返回了4条数据,"info" : "清晨下的第一杯水"也被查询了出来,其实是因为我们使用了 ik 分词器,根据“一顿操作”中的“一”匹配到了这条数据

一般的,我们推荐使用构建查询,以后在与程序交互时的查询等也是使用构建查询方式处理查询条件,因为该方式可以构建更加复杂的查询条件,也更加一目了然

查询全部

GET /user/_doc/_search
{
  "query":{
    "match_all":{}
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "kunkun",
          "age" : 3,
          "sex" : "男",
          "info" : "吉你实在实在太美",
          "tags" : [
            "唱",
            "跳",
            "篮球"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

match_all 的值为空,表示没有查询条件,就像 select * from table_name 一样。

多字段匹配查询

multi_match 与 match 类似,不同的是它可以在多个字段中查询。

GET /user/_search
{
  "query": {
    "multi_match": {
      "query": "zhangsan",
      "fields": ["name","info"]
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.3862942,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.3862942,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

再查询“一顿操作”

GET /user/_search
{
  "query": {
    "multi_match": {
      "query": "一顿操作",
      "fields": ["name","info"]
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.9004039,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.3176721,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        }
      }
    ]
  }
}

可以看到,只要有一个字段的值匹配成功就都可以查询出来

指定返回字段

GET /user/_doc/_search
{
  "query":{
    "match": {
      "info": "一顿操作"
    }
  },
  "_source": ["info","name"]
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.9004039,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "wei",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan1111",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.3176721,
        "_source" : {
          "name" : "lisi",
          "info" : "清晨下的第一杯水"
        }
      }
    ]
  }
}

排序查询

sort指定某个字段的排序规则,desc 是降序,asc 是升序

GET /user/_doc/_search
{
  "query":{
    "match": {
      "info": "一顿操作"
    }
  },
  "sort":{
    "age":{
      "order":"desc"
    }
  },
  "_source": ["info","name","age"]
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "info" : "清晨下的第一杯水"
        },
        "sort" : [
          66
        ]
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "info" : "一顿操作猛如虎,一看工资2500"
        },
        "sort" : [
          18
        ]
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : null,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "info" : "一顿操作猛如虎,一看工资2500"
        },
        "sort" : [
          18
        ]
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : null,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "info" : "一顿操作猛如虎,一看工资2500"
        },
        "sort" : [
          18
        ]
      }
    ]
  }
}

注意:在排序的过程中,只能使用可排序的属性进行排序。那么可以排序的属性有哪些呢?

  • 数字
  • 日期
  • ID

其他都不行!

分页查询

from是起始数据的下标,0代表从第一条数据开始,size是每页有多少条数据

GET /user/_doc/_search
{
  "query":{
    "match": {
      "info": "一顿操作"
    }
  },
  "sort":{
    "age":{
      "order":"desc"
    }
  },
  "_source": ["info","name","age"],
  "from":0,
  "size":2
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "info" : "清晨下的第一杯水"
        },
        "sort" : [
          66
        ]
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "info" : "一顿操作猛如虎,一看工资2500"
        },
        "sort" : [
          18
        ]
      }
    ]
  }
}

布尔查询

must 查询

must 相当于 mysql 中的 and,根据多个条件进行查询

GET /user/_doc/_search
{
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "name":"zhangsan"
          }
        },
        {
          "match":{
            "age":18
          }
        }
      ]
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 2.3862944,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.3862944,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

should 查询

相当于 mysql 中的 or,只需要满足其中一个条件即可

GET /user/_doc/_search
{
  "query":{
    "bool":{
      "should":[
        {
          "match":{
            "name":"kunkun"
          }
        },
        {
          "match":{
            "age":18
          }
        }
      ]
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.3862942,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.3862942,
        "_source" : {
          "name" : "kunkun",
          "age" : 3,
          "sex" : "男",
          "info" : "吉你实在实在太美",
          "tags" : [
            "唱",
            "跳",
            "篮球"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

must_not 查询

查询出不满足条件的所有数据

GET /user/_doc/_search
{
  "query":{
    "bool":{
      "must_not":[
        {
          "match":{
            "age":18
          }
        }
      ]
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.0,
        "_source" : {
          "name" : "kunkun",
          "age" : 3,
          "sex" : "男",
          "info" : "吉你实在实在太美",
          "tags" : [
            "唱",
            "跳",
            "篮球"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.0,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        }
      }
    ]
  }
}

filter 查询

条件过滤查询,示例:查询出年龄大于20的数据

GET /user/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "range":{
          "age":{
            "gt":20
          }
        }
      }
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.0,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        }
      }
    ]
  }
}
  • gt 表示大于
  • gte 表示大于等于
  • lt 表示小于
  • lte 表示小于等于

如果想要查询出10~20之间的数据:

GET /user/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "range":{
          "age":{
            "gt":10,
            "lt":20
          }
        }
      }
    }
  }
}

结果:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.0,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 0.0,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 0.0,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

精确查询 term

term查询是直接通过倒排索引指定的词条,也就是精确查找。

term 与 match 区别:

  • match 是经过分析(analyer)的,也就是说,文档是先被分析器处理了,根据不同的分析器,分析出的结果也会不同,在会根据分词结果进行匹配。
  • term 是不经过分词的,直接去倒排索引查找精确的值。

这里我们重新定义一个索引,并添加两条数据:

PUT user1
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "info":{
        "type": "keyword"
      }
    }
  }
}
PUT /user1/_doc/1
{
  "name":"张三三",
  "info":"一顿操作猛如虎,一看工资2500"
}
PUT /user1/_doc/2
{
  "name":"李四四",
  "info":"清晨的第一杯水"
}

其中,name 类型是 text,info 类型是 keyword

接下来我们查询 name 为张的数据

GET /user1/_search
{
  "query": {
    "term": {
      "name": "张"
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.8547784,
    "hits" : [
      {
        "_index" : "user1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.8547784,
        "_source" : {
          "name" : "张三三",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      }
    ]
  }
}

能够查询到 name 为张三三的数据

接下来我们查询 name 为张三三的数据

GET /user1/_search
{
  "query": {
    "term": {
      "name": "张三三"
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

没有查询出任何数据,这是因为 name 的类型是 text,我们的 ik分词器对张三三进行了分词拆分,而 term 查询的条件张三三不可拆分,故查询不到

接下来查询 info 为“一”的数据

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

查询不到任何数据

查询 info 为“一顿操作猛如虎,一看工资2500”的数据

GET /user1/_search
{
  "query": {
    "term": {
      "info": "一顿操作猛如虎,一看工资2500"
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.6931471,
    "hits" : [
      {
        "_index" : "user1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6931471,
        "_source" : {
          "name" : "张三三",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      }
    ]
  }
}

结果可以查询到

所以 term 通常用来查询类型为 keyword 的字段

多关键字精确查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。

如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于 mysql 的 in

GET /user1/_search
{
  "query": {
    "terms": {
      "name": ["张","李"]
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "张三三",
          "info" : "一顿操作猛如虎,一看工资2500"
        }
      },
      {
        "_index" : "user1",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "李四四",
          "info" : "清晨的第一杯水"
        }
      }
    ]
  }
}

fuzzy 查询

fuzzy 查询返回包含与搜索字词相似的字词的文档。

编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:

  • 更改字符(box → fox)
  • 删除字符(black → lack)
  • 插入字符(sic → sick)
  • 转置两个相邻字符(act → cat)

为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。

通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。

GET /user/_search
{
  "query": {
    "fuzzy": {
      "name": "zhangsan1"
    }
  }
}

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.2130076,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.2130076,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}

指定 fuzziness 编辑距离

GET /user/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "zhangsan11",
        "fuzziness": 2
      }
    }
  }
}

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.1090355,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.1090355,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0397208,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        }
      }
    ]
  }
}
GET /user/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "zhangsan11",
        "fuzziness": 1
      }
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

聚合查询

聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by,当然还有很多其他的聚合,例如取最大值、平均值等等。

对某个字段取最大值

GET /user/_search
{
  "aggs": {
    "max_age": { # 自定义名字
      "max": {
        "field": "age"
      }
    }
  },
  "size": 0
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "max_age" : {
      "value" : 66.0
    }
  }
}

可以看到aggregations中最大值为66.0

取总和

GET /user/_search
{
  "aggs": {
    "sum_age": {
      "sum": {
        "field": "age"
      }
    }
  },
  "size": 0
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "sum_age" : {
      "value" : 123.0
    }
  }
}

年龄总和为123.0

取平均值

GET /user/_search
{
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  },
  "size": 0
}

结果:

{
  "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" : {
    "avg_age" : {
      "value" : 24.6
    }
  }
}

年龄平均值为24.6

对某个字段的值进行去重之后再取个数

GET /user/_search
{
  "aggs": {
    "distinct_age":{
      "cardinality": {
        "field": "age"
      }
    }
  },
  "size": 0
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "distinct_age" : {
      "value" : 3
    }
  }
}

去重后,数据个数为3个

State 聚合

stats 聚合,对某个字段一次性返回 count,max,min,avg 和 sum 五个指标

GET /user/_search
{
  "aggs": {
    "state_age":{
      "stats": {
        "field": "age"
      }
    }
  },
  "size": 0
}

结果:

{
  "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" : {
    "state_age" : {
      "count" : 5,
      "min" : 3.0,
      "max" : 66.0,
      "avg" : 24.6,
      "sum" : 123.0
    }
  }
}

高亮查询

使用highlight根据查询条件,指定你要高亮的字段

GET /user/_search
{
  "query": {
    "match": {
      "info": "一顿操作"
    }
  },
  "highlight": {
    "fields": {
      "info": {}
    }
  }
}

结果:

{
  "took" : 43,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.9004039,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<em>一</em><em>顿</em><em>操</em><em>作</em>猛如虎,<em>一</em>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<em>一</em><em>顿</em><em>操</em><em>作</em>猛如虎,<em>一</em>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<em>一</em><em>顿</em><em>操</em><em>作</em>猛如虎,<em>一</em>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.3176721,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        },
        "highlight" : {
          "info" : [
            "清晨下的第<em>一</em>杯水"
          ]
        }
      }
    ]
  }
}

可以看到查询条件“一顿操作”的每个字(分词结果)都进行了高亮处理,默认标签是<em>

自定义高亮样式

使用pre_tags定义前缀标签,post_tags定义后缀标签

GET /user/_search
{
  "query": {
    "match": {
      "info": "一顿操作"
    }
  },
  "highlight": {
    "pre_tags": "<b class='key' style='color:red'>",
    "post_tags": "</b>", 
    "fields": {
      "info": {}
    }
  }
}

结果:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.9004039,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<b class='key' style='color:red'>一</b><b class='key' style='color:red'>顿</b><b class='key' style='color:red'>操</b><b class='key' style='color:red'>作</b>猛如虎,<b class='key' style='color:red'>一</b>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "wei",
          "age" : 18,
          "sex" : "女",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<b class='key' style='color:red'>一</b><b class='key' style='color:red'>顿</b><b class='key' style='color:red'>操</b><b class='key' style='color:red'>作</b>猛如虎,<b class='key' style='color:red'>一</b>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.9004039,
        "_source" : {
          "name" : "zhangsan1111",
          "age" : 18,
          "sex" : "男",
          "info" : "一顿操作猛如虎,一看工资2500",
          "tags" : [
            "计算机",
            "运动",
            "动漫"
          ]
        },
        "highlight" : {
          "info" : [
            "<b class='key' style='color:red'>一</b><b class='key' style='color:red'>顿</b><b class='key' style='color:red'>操</b><b class='key' style='color:red'>作</b>猛如虎,<b class='key' style='color:red'>一</b>看工资2500"
          ]
        }
      },
      {
        "_index" : "user",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.3176721,
        "_source" : {
          "name" : "lisi",
          "age" : 66,
          "sex" : "女",
          "info" : "清晨下的第一杯水",
          "tags" : [
            "a",
            "b",
            "c"
          ]
        },
        "highlight" : {
          "info" : [
            "清晨下的第<b class='key' style='color:red'>一</b>杯水"
          ]
        }
      }
    ]
  }
}

需要注意的是:自定义标签中属性或样式中的逗号一律用英文状态的单引号表示,应该与外部 es 语法的双引号区分开。

说明:Deprecation

注意 es 在第一个版本的开始每个文档都储存在一个索引中,并分配一个 映射类型,映射类型用于表示被索引的文档或者实体的类型,这样带来了一些问题, 导致后来在 es 6.0.0 版本中一个文档只能包含一个映射类型,而在 7.0.0 中,映射类型则将被弃用,到了 8.0.0 中则将完全被删除。

只要记得,一个索引下面只能创建一个类型就行了,其中各字段都具有唯一性,如果在创建映射的时候,如果没有指定文档类型,那么该索引的默认索引类型是 _doc ,不指定文档id 则会内部帮我们生成一个 id字符串。