当前版本 7.0 : https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
5.6的版本的: https://www.elastic.co/guide/en/elasticsearch/reference/5.6/index.html
新建索引 book
{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
},
"mappings":{
"novel":{
"properties":{
"word_count":{
"type":"integer"
},
"author":{
"type":"keyword"
},
"title":{
"type":"text"
},
"publish_date":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
}
}
}
}
}
新增数据
多增加几条数据
再增加个artisan 索引
GET /_search
将会返回所有索引中所有的文档
可以查询一个, 多个或 _all 索引(indices)或类型(types) ,index支持通配符
GET /b*k/type1,type2/_search
将会返回指定查询条件的文档
POST http://localhost:9200/*k/novel/_search
GET /_search
{
"from": 30,
"size": 10
}
Get请求也能携带参数? 是不是很别扭? 因为携带交互数据的 GET 请求并不被广泛支持, 所以 search API同样支持 POST 请求, 类似于这样:
POST /_search
{
"from": 30,
"size": 10
}
这个原理同样应用于其他携带交互数据的 GET API请求中
POST http://localhost:9200/book/novel/_search
结构化查询Query DSL是一种灵活的, 多表现形式的查询语言。 Elasticsearch在一个简单的JSON接口中用结构化查询来展现Lucene的绝大多数能力, 使用DSL查询能够让查询更加灵活, 精准, 易于阅读并且易于debug。
使用结构化查询, 需要query 参数
GET /_search
{
"query": YOUR_QUERY_HERE
}
空查询 - {} - 在功能上等同于使用 match_all 查询子句, 正如其名字一样, 匹配所有的文档
POST http://localhost:9200/book/novel/_search
语法如下:
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
或指向一个指定的字段
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
举个例子: 使用 match 查询子句用来找寻在 title字段中找寻包含 elasticsearch 的成员
{
"match": {
"title": "Elasticsearch"
}
}
完整的查询请求如下
必须使用query关键字 , url中必须使用_search
POST http://localhost:9200/book/novel/_search
查询子句就像是搭积木一样, 可以合并简单的子句为一个复杂的查询语句。
在关系型数据库中有很多条件判断,比如 等于= 不等于!= ,或者 or ,在es中
minimum_should_match
举个例子,查找 title包含Elasticsearch ,并且作者不能为李四的记录
{
"query":{
"bool":{
"must":{
"match":{
"title":"Elasticsearch"
}
},
"must_not":{
"match":{
"author":"李四"
}
}
}
}
}
POST http://localhost:9200/book/novel/_search
查询与过滤语句非常相似, 但是它们由于使用目的不同而稍有差异。
一条过滤语句会询问每个文档的字段值是否包含着特定值, 比如 是否 createTime 的日期范围某个时间段内? 是否 status 字段中包含单词 “published” ?
_score
, 并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。原则上来说, 使用查询语句做全文本搜索或其他需要进行相关性评分的时候, 剩下的全部用过滤语句
使用 match_all 可以查询到所有文档, 是没有查询条件下的默认语句
POST http://localhost:9200/book/novel/_search
{
"query":{
"match_all":{}
}
}
match 查询是一个标准查询, 不管你需要全文本查询还是精确查询基本上都要用到它。
如果你使用 match 查询一个全文本字段, 它会在真正查询之前用分析器先分析 match 一下查询字符:
POST http://localhost:9200/book/novel/_search
{
"query":{
"match":{
"title":"Elasticsearch"
}
}
}
如果用 match 下指定了一个确切值, 在遇到数字, 日期, 布尔值或者 not_analyzed 的字符串时, 它将为你搜索你给定的值,举几个例子
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
例子
做精确匹配搜索时最好用过滤语句, 因为过滤语句可以缓存数据。
multi_match 查询允许你做 match 查询的基础上同时搜索多个字段
{
"multi_match": {
"query": "full text search",
"fields": [
"title",
"body"
]
}
}
POST http://localhost:9200/book/novel/_search
{
"query":{
"multi_match":{
"query":"李四",
"fields":["author","title"]
}
}
}
bool 查询与 bool 过滤相似, 用于合并多个查询子句。 不同的是, bool 过滤可以直接给出是否匹配成功, 而 bool 查询要计算每一个查询子句的 _score (相关性分值)
{
"bool": {
"must": {
"match": {
"title": "how to make millions"
}
},
"must_not": {
"match": {
"tag": "spam"
}
},
"should": [
{
"match": {
"tag": "starred"
}
},
{
"range": {
"date": {
"gte": "2014-01-01"
}
}
}
]
}
}
上述查询将会找到 title 字段中包含 “how to make millions”, 并且 “tag” 字段没有被标为 spam. 如果有标识为 "starred"或者发布日期为2014年之前, 那么这些匹配的文档将比同类网站等级高.
如果 bool 查询下没有 must 子句, 那至少应该有一个 should 子句。 但是 如果有 must 子句, 那么没有 should 子句也可以进行查询。
term 主要用于精确匹配哪些值, 比如数字, 日期, 布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)
term仅允许指定一个匹配条件 ,即 value只能有一个值
举例:过滤查询"public_date" 精确匹配 "2017-08-15"的数据
{
"query":{
"term":{
"public_date": "2017-08-15"
}
}
}
POST http://localhost:9200/book/novel/_search
terms 允许指定多个匹配条件。 如果某个字段指定了多个值, 那么文档需要一起去做匹配。
例子 查询author匹配 "李三"或者"孙悟空"的数据
POST http://localhost:9200/book/novel/_search
{
"query":{
"terms":{
"author":["李三","孙悟空"]
}
}
}
range 过滤 按照指定范围查找一批数据
范围操作符包含:
例子: 过滤查询 字数 大于等于1000 小于2000的数据 POST http://localhost:9200/book/novel/_search
{
"query":{
"range":{
"word_count":{
"gte":1000,
"lt":"2000"
}
}
}
}
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段, 类似于SQL语句中的 IS_NULL 条件。
这两个过滤只是针对已经查出一批数据来, 但是想区分出某个字段是否存在的时候使用。
目前es不推荐使用missing过滤, 使用bool.must_not + exists来替代
"bool": {
"must_not": {
"exists": {
"field": "title"
}
}
}
例子 查询是否存在 名为 xxxx 的字段
POST http://localhost:9200/book/novel/_search
{
"query":{
"exists":{
"field":"xxxx"
}
}
}
bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:
例子
{
"query": {
"bool": {
"must": {
"term": {
"folder": "inbox"
}
},
"must_not": {
"term": {
"tag": "spam"
}
},
"should": [
{
"term": {
"starred": true
}
},
{
"term": {
"unread": true
}
}
]
}
}
}
查询语句和过滤语句可以放在各自的上下文中。 在 ElasticSearch API 中我们会看到许多带有 query 或 filter 的语句。
这些语句既可以包含单条 query 语句, 也可以包含一条 filter 子句。
换句话说, 这些语句需要首先创建一个 query 或 filter 的上下文关系。
复合查询语句可以加入其他查询子句, 复合过滤语句也可以加入其他过滤子句。 通常情况下, 一条查询语句需要过滤语句的辅助, 全文本搜索除外。
所以说, 查询语句可以包含过滤子句, 反之亦然。 以便于我们切换 query 或 filter 的上下文。 这就要求我们在读懂需求的同时构造正确有效的语句。
假设我们有这样一条查询语句:
{
"match": {
"email": "business opportunity"
}
}
然后我们想要让这条语句加入 term 过滤, 在收信箱中匹配邮件:
{
"term": {
"folder": "inbox"
}
}
search API中只能包含 query 语句, 所以我们需要用 filtered 来同时包含 “query” 和 “filter” 子句 【过滤查询已被弃用,并在ES 5.0中删除,如下会在我们用的5.x版本中报错】
{
"filtered": {
"query": {
"match": {
"email": "business opportunity"
}
},
"filter": {
"term": {
"folder": "inbox"
}
}
}
}
我们在外层再加入 query 的上下文关系:
{
"query": {
"filtered": {
"query": {
"match": {
"email": "business opportunity"
}
},
"filter": {
"term": {
"folder": "inbox"
}
}
}
}
}
报错了。。。。
改成使用bool / must / filter查询
{
"query": {
"bool": {
"must": {
"match": {
"email": "business opportunity"
}
},
"filter": {
"term": {
"folder": "inbox"
}
}
}
}
}
在 query 上下文中, 如果你只需要一条过滤语句, 比如在匹配全部邮件的时候, 你可以 省略 query 子句( 5.x以后的版本 需要用bool 代替 filtered):
{
"query": {
"bool": {
"filter": {
"term": {
"folder": "inbox"
}
}
}
}
}
如果一条查询语句没有指定查询范围, 那么它默认使用 match_all 查询 ,等同于
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"term": {
"folder": "inbox"
}
}
}
}
}
上面说的是 查询中使用过滤。 那过滤中使用查询呢?
我们很少用到的过滤语句中包含查询,为了语法的完整性,ES也支持这种。 只有在过滤中用到全文本匹配时候才会使用这种结构。
查询语句可以变得非常复杂, 特别是与不同的分析器和字段映射相结合后。
validate API 可以验证一条查询语句是否合法。
POST http://localhost:9200/book/novel/_validate/query
重点看 valid 的返回结果
想知道语句非法的具体错误信息, 需要加上 explain 参数:
POST: http://localhost:9200/book/novel/_validate/query?explain
如果是合法语句的话, 使用 explain 参数可以返回一个带有查询语句的可阅读描述, 可以帮助了解查询语句在ES中是如何执行的
以 以下的JSON为例
{
"query":{
"match":{
"title":"Elasticserach"
}
}
}
POST http://localhost:9200/book/novel/_validate/query?explain
关键请求: /_validate/query?explain
返回:
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "book",
"valid": true,
"explanation": "+title:elasticserach #_type:novel"
}
]
}
explanation 会为每一个索引返回一段描述, 因为每个索引会有不同的映射关系和分析器. 上面的就只有一个。 ES如何查询是和分词器有关的。