上一篇对查询按照简单查询、条件查询、聚合查询进行了分类,并逐一介绍了基本用法。
本文对条件查询再进行分类,介绍子条件查询和复合条件查询。
条件查询分类
子条件查询:特定字段查询 所指特定值。
复合条件查询:以一定的逻辑 组合 子条件查询。
子条件查询
子条件查询又分为:Query context 和 Filter Context。
在查询过程中,除了判断文档是否满足查询条件外,ES还为计算一个_score来标识匹配的程度,旨在判断目标文档和查询条件匹配的有多好。
Query context
Query context 常用的查询包括:
全文本查询:针对文本类型的数据
字段级别的查询:针对结构化的数据,比如数字、日期等
概念树状图
说了这么多概念,画个树吧:
全文本查询
全文本查询 包括:模糊匹配、习语匹配、多个字段的匹配查询、语法的查询。
下面,我们在上一篇文章录入的的索引和文档的基础上继续进行查询。具体的索引结构和文档数据请翻看上一篇文章。
我们创建了一个rent索引,一个community类型,以及对应的18个文档。
示例数据是之前写的文章里的,这里不在累述,我把索引定义给出:
{
"state": "open",
"settings": {
"index": {
"creation_date": "1523632189666",
"number_of_shards": "3",
"number_of_replicas": "1",
"uuid": "lUrZ_KHtQcuG33MFNivX-A",
"version": {
"created": "5060899"
},
"provided_name": "rent"
}
},
"mappings": {
"community": {
"properties": {
"creationdate": {
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis",
"type": "date"
},
"city": {
"type": "keyword"
},
"communityname": {
"type": "text"
},
"age": {
"type": "integer"
}
}
},
"shop": { }
},
"aliases": [ ],
"primary_terms": {
"0": 2,
"1": 2,
"2": 2
},
"in_sync_allocations": {
"0": [
"0RFsy8yXT6WM25oL8n5gew"
,
"QfWzYOCWQYy_QISycd-PNg"
],
"1": [
"MBaaq2YfQRmrR1hZx6qqhQ"
,
"iIxY5sN8Q3m6CR4Q5TxzXw"
],
"2": [
"vEbuzvxzTW2y_mokZWQSig"
,
"VhIOetKsSDqeOnG3HisH_w"
]
}
}
(本文出自oschina博主happybks的博文:https://my.oschina.net/happyBKs/blog/1799387)
模糊匹配
模糊匹配,使用match关键词,对文本类型字段进行匹配时,会按照条件值中的各个字或者说分词进行匹配。
POST http://localhost:9200/rent/community/_search
{
"query":{
"match":{
"communityname":"中海万锦城(二期)"
}
}
}
结果除了包含中海万锦城(二期)、包括其他communityname字段包含“中”“海”“万”等字的文档。
因为这是模糊匹配,完全一样的、包含中海的、包含一个万字文档,匹配的程度不同,_score的分数也不同。返回结果按照匹配度,即_score分数由高到低(但是_score大于0,若等于0表示完全不匹配就不会被模糊查询到)排列。
查询结果
{
"took": 253,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 10.104993,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGp3aoILHeA4gRvWM",
"_score": 10.104993,
"_source": {
"communityname": "中海万锦城(二期)",
"city": "上海闸北不夜城",
"age": 6,
"creationdate": "2012-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGbCzoILHeA4gRvWL",
"_score": 3.335333,
"_source": {
"communityname": "中海悦府",
"city": "上海松江泗泾",
"age": 4,
"creationdate": "2014-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHR2loILHeA4gRvWN",
"_score": 2.0010364,
"_source": {
"communityname": "中海紫御豪庭",
"city": "上海普陀长征",
"age": 6,
"creationdate": "2012-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHsN6oILHeA4gRvWO",
"_score": 1.6676666,
"_source": {
"communityname": "象屿鼎城",
"city": "上海浦东川沙",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZDcK7oILHeA4gRvWB",
"_score": 1.2871116,
"_source": {
"communityname": "万科蓝山",
"city": "上海浦东曹路",
"age": 14,
"creationdate": "2004-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 0.91251767,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 0.7981695,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZC1HYoILHeA4gRvV_",
"_score": 0.7981695,
"_source": {
"communityname": "万科优诗美地",
"city": "上海闵行七宝",
"age": 19,
"creationdate": "1999-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLY7wnkoILHeA4gRvV8",
"_score": 0.36413702,
"_source": {
"communityname": "万科阳光苑",
"city": "上海",
"age": 10,
"creationdate": "2008-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZDK3-oILHeA4gRvWA",
"_score": 0.36413702,
"_source": {
"communityname": "万科清林径",
"city": "上海浦东新区新场镇",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
}
]
}
}
习语匹配
如果你希望将查询条件中的值作为一个固定的习语进行匹配,而不是根据匹配程度进行模糊匹配,可以使用习语匹配。关键词是match_phrase
POST http://localhost:9200/rent/community/_search
{
"query":{
"match_phrase":{
"communityname":"中海万锦城(二期)"
}
}
}
查询结果:
此时查询结果我们发现只一条了。
{
"took": 568,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 10.104993,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGp3aoILHeA4gRvWM",
"_score": 10.104993,
"_source": {
"communityname": "中海万锦城(二期)",
"city": "上海闸北不夜城",
"age": 6,
"creationdate": "2012-01-01"
}
}
]
}
}
多个字段的匹配查询
多个字段的模糊匹配查询 需要用到关键词multi_match,然后里面套query和fields关键词,指明查询条件文本和需要匹配哪些字段。
POST http://localhost:9200/rent/community/_search
{
"query":{
"multi_match":{
"query":"山江",
"fields":["communityname","city"]
}
}
}
查询结果:
可以看到小区名称或者地址信息中包含“山”或“江”的小区文档都被模糊匹配查询到了。
{
"took": 17,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 1.7792181,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEy0foILHeA4gRvWE",
"_score": 1.7792181,
"_source": {
"communityname": "金地艺境(宝山)",
"city": "上海宝山区",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 1.7792181,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZDcK7oILHeA4gRvWB",
"_score": 1.2871116,
"_source": {
"communityname": "万科蓝山",
"city": "上海浦东曹路",
"age": 14,
"creationdate": "2004-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFA5EoILHeA4gRvWF",
"_score": 1.0751344,
"_source": {
"communityname": "金地艺境(松江)",
"city": "上海松江区",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
}
]
}
}
语法查询
所谓语法查询,就是根据一定的语法规则进行的查询。经常在Kibana中用,是做数据搜索用的,支持通配符、范围查询、布尔查询、正则表达式等。语法十分丰富。关键词query_string。
逻辑与AND
有多个条件可以用逻辑与,关键词AND
POST http://localhost:9200/rent/community/_search
{
"query":{
"query_string":{
"query":"万科 AND 大道"
}
}
}
结果:
{
"took": 386,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 2.9101574,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 2.9101574,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
}
]
}
}
逻辑或OR
如果是逻辑或,关键词OR。并且,语法条件可以组合。
POST http://localhost:9200/rent/community/_search
{
"query":{
"query_string":{
"query":"(万科 AND 大道) OR 象屿"
}
}
}
结果:
{
"took": 324,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 4.0250216,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHsN6oILHeA4gRvWO",
"_score": 4.0250216,
"_source": {
"communityname": "象屿鼎城",
"city": "上海浦东川沙",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 2.9101574,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
}
]
}
}
多个字段的语法匹配
这个和多字段模糊匹配时的关键词一样,需要用到fields关键词,然后在列表里把所涉及的字段名称给出。
POST http://localhost:9200/rent/community/_search
{
"query":{
"query_string":{
"query":"公园 OR 闵行",
"fields":["communityname","city"]
}
}
}
查询结果:
{
"took": 53,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 2.1502688,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 2.1502688,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 1.1690899,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 1.0225905,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 1.0225905,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
}
]
}
}
字段级别的查询
字段级别的查询,或者说结构化查询,在query下的关键词需要用term。
特定值查询
比如查询房龄为10年的小区:
POST http://localhost:9200/rent/community/_search
{
"query":{
"term":{
"age":10
}
}
}
结果:
{
"took": 197,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLY7wnkoILHeA4gRvV8",
"_score": 1,
"_source": {
"communityname": "万科阳光苑",
"city": "上海",
"age": 10,
"creationdate": "2008-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZF4FAoILHeA4gRvWI",
"_score": 1,
"_source": {
"communityname": "保利西子湾",
"city": "上海松江大学城",
"age": 10,
"creationdate": "2008-01-01"
}
}
]
}
}
这时,我们尝试像之前模糊匹配的示例那样在字段级别查询里查询“万科”
注意:关键词是字段级别查询的关键词term。
POST http://localhost:9200/rent/community/_search
{
"query":{
"term":{
"communityname":"万科"
}
}
}
结果,发现查询结果的数量是0。而之前用match做全文本查询时,查询“万科”,会得到一大推communityname的值中包含“万”或“科”字的文档。
{
"took": 14,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
那我们在尝试一下输入完整的字段值。如果我们将term中条件communityname字段的值设置为一个完全存在的值,例如:万科公园大道
{
"query":{
"term":{
"communityname": "万科公园大道"
}
}
}
结果发现,依然没有返回结果。因为commmunityname字段是text文本类型。不适用于字段级别的查询。
如果我们换成city字段,就没有问题:
{
"query":{
"term":{
"city": "上海老闵行"
}
}
}
结果,返回了对应的结果,因为city字段是keyword类型:
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.2039728,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 1.2039728,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
}
]
}
}
范围查询
字段级别的查询,还可以查询特定字段一定范围值内的文档有哪些。这种涉及字段值范围的条件,需要用到关键词range。范围描述的关键词与mongo中的十分类似。
关键词 | 含义 | 数学符号 |
gt | 大于 | > ( |
gte | 大于等于 | ≥ [ |
lt | 小于 | < ) |
lte | 小于等于 | ≤ ] |
我们来查一下,房龄在5到7年(含5年,不含7年)的小区有哪些:age的字段类型是integer
{
"query":{
"range":{
"age": {
"gte":5,
"lt":7
}
}
}
}
查询结果:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZDK3-oILHeA4gRvWA",
"_score": 1,
"_source": {
"communityname": "万科清林径",
"city": "上海浦东新区新场镇",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGp3aoILHeA4gRvWM",
"_score": 1,
"_source": {
"communityname": "中海万锦城(二期)",
"city": "上海闸北不夜城",
"age": 6,
"creationdate": "2012-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEy0foILHeA4gRvWE",
"_score": 1,
"_source": {
"communityname": "金地艺境(宝山)",
"city": "上海宝山区",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHsN6oILHeA4gRvWO",
"_score": 1,
"_source": {
"communityname": "象屿鼎城",
"city": "上海浦东川沙",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFV2doILHeA4gRvWG",
"_score": 1,
"_source": {
"communityname": "金地艺华年",
"city": "上海浦东航头",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHR2loILHeA4gRvWN",
"_score": 1,
"_source": {
"communityname": "中海紫御豪庭",
"city": "上海普陀长征",
"age": 6,
"creationdate": "2012-01-01"
}
}
]
}
}
日期字段范围查询
字段级别的范围查询同时还支持日期类型:
(字段级别查询:“看吧,所有类型我都支持,我就不支持你文本text类型,谁让你和全文本类型打得火热”)
POST http://localhost:9200/rent/community/_search
{
"query":{
"range":{
"creationdate": {
"gte":"2011-12-31",
"lt":"2014-01-01"
}
}
}
}
返回结果:
{
"took": 358,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZDK3-oILHeA4gRvWA",
"_score": 1,
"_source": {
"communityname": "万科清林径",
"city": "上海浦东新区新场镇",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGp3aoILHeA4gRvWM",
"_score": 1,
"_source": {
"communityname": "中海万锦城(二期)",
"city": "上海闸北不夜城",
"age": 6,
"creationdate": "2012-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEy0foILHeA4gRvWE",
"_score": 1,
"_source": {
"communityname": "金地艺境(宝山)",
"city": "上海宝山区",
"age": 6,
"creationdate": "2012-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHsN6oILHeA4gRvWO",
"_score": 1,
"_source": {
"communityname": "象屿鼎城",
"city": "上海浦东川沙",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFV2doILHeA4gRvWG",
"_score": 1,
"_source": {
"communityname": "金地艺华年",
"city": "上海浦东航头",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHR2loILHeA4gRvWN",
"_score": 1,
"_source": {
"communityname": "中海紫御豪庭",
"city": "上海普陀长征",
"age": 6,
"creationdate": "2012-01-01"
}
}
]
}
}
如果要表示现在,可以使用关键词now。
比如查询2015年至今的新小区:
POST http://localhost:9200/rent/community/_search
{
"query":{
"range":{
"creationdate": {
"gte":"2015-01-01",
"lt":"now"
}
}
}
}
结果:
{
"took": 80,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 1,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFA5EoILHeA4gRvWF",
"_score": 1,
"_source": {
"communityname": "金地艺境(松江)",
"city": "上海松江区",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGGD2oILHeA4gRvWJ",
"_score": 1,
"_source": {
"communityname": "保利艾庐",
"city": "上海浦东新区周浦镇",
"age": 3,
"creationdate": "2015-01-01"
}
}
]
}
}