Elasticsearch-05Elasticsearch之查询与过滤

版权声明:【show me the code ,change the world】 https://blog.csdn.net/yangshangwei/article/details/89413027

官方API文档

当前版本 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 索引

Types


请求体查询

空查询

GET      /_search

将会返回所有索引中所有的文档

在这里插入图片描述


可以查询一个, 多个或 _all 索引(indices)或类型(types) ,index支持通配符

GET     /b*k/type1,type2/_search

将会返回指定查询条件的文档

在这里插入图片描述

POST http://localhost:9200/*k/novel/_search

在这里插入图片描述


from 及 size 参数进行分页

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

在这里插入图片描述


合并多子句

查询子句就像是搭积木一样, 可以合并简单的子句为一个复杂的查询语句。

  • 简单子句(leaf clauses)(比如 match 子句)用以在将查询字符串与一个字段(或多字段)进行比较
  • 复合子句(compound)用以合并其他的子句。 例如, bool 子句允许你合并其他的合法子句, 无论是 must , must_not 还是 should .
  • 复合子句可以合并多种子句为一个单一的查询, 无论是简单子句还是其他的复合子句

在关系型数据库中有很多条件判断,比如 等于= 不等于!= ,或者 or ,在es中

  • must 需要满足条件 ==或like
  • must_not 不需要在满足条件内的 !=或 not like
  • should: should中的两个条件至少满足一个就可以,should下有多个条件时注意加参数 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” ?

查询语句与过滤语句的区别

  • Query查询语句会询问每个文档的字段值与特定值的匹配程度如何,ES会给出一个相关性评分 _score , 并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。
  • Query查询语句不仅要查找相匹配的文档, 还需要计算每个文档的相关性, 所以一般来说查询语句要比过滤语句更耗时, 并且查询结果也不可缓存
  • Filter过滤查询语句在查询过程中,只判断该文档是否满足条件,只有yes和no。用作过滤不用做模糊查询. 对fifter es会用缓存,相对query来说会更快

原则上来说, 使用查询语句做全文本搜索或其他需要进行相关性评分的时候, 剩下的全部用过滤语句


Query DSL

match_all 查询

使用 match_all 可以查询到所有文档, 是没有查询条件下的默认语句

POST http://localhost:9200/book/novel/_search

{
	"query":{
		"match_all":{}
	}
}


match 查询

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 查询

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 过滤可以直接给出是否匹配成功, 而 bool 查询要计算每一个查询子句的 _score (相关性分值)

  • must :: 查询指定文档一定要被包含。
  • must_not :: 查询指定文档一定不要被包含。
  • should :: 查询指定文档, 有则可以为文档相关性加分
{
    "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 子句也可以进行查询。


Filter DSL

term 过滤

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 过滤

terms 允许指定多个匹配条件。 如果某个字段指定了多个值, 那么文档需要一起去做匹配。

例子 查询author匹配 "李三"或者"孙悟空"的数据

POST http://localhost:9200/book/novel/_search

{
	"query":{
		"terms":{
			"author":["李三","孙悟空"]
		}
	}
}

在这里插入图片描述


range 过滤

range 过滤 按照指定范围查找一批数据

范围操作符包含:

  • gt 大于
  • gte 大于等于
  • lt 小于
  • lte 小于等于

例子: 过滤查询 字数 大于等于1000 小于2000的数据
POST http://localhost:9200/book/novel/_search

{
	"query":{
		"range":{
			"word_count":{
				"gte":1000,
				"lt":"2000"
			}
		}
	}
}

在这里插入图片描述


exists 和 missing 过滤

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 过滤

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

  • must :: 多个查询条件的完全匹配,相当于 and。
  • must_not :: 多个查询条件的相反匹配,相当于 not。
  • should :: 至少有一个查询条件匹配, 相当于 or。

这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:

例子

{
    "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)

查询语句可以变得非常复杂, 特别是与不同的分析器和字段映射相结合后。

validate API 可以验证一条查询语句是否合法。

POST http://localhost:9200/book/novel/_validate/query

在这里插入图片描述

重点看 valid 的返回结果

在这里插入图片描述


查看错误信息

想知道语句非法的具体错误信息, 需要加上 explain 参数:

POST: http://localhost:9200/book/novel/_validate/query?explain

在这里插入图片描述

查看ES如何执行的

如果是合法语句的话, 使用 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如何查询是和分词器有关的。

猜你喜欢

转载自blog.csdn.net/yangshangwei/article/details/89413027