ES dsl搜索

QueryString的方式查询数据

名称 备注
请求方式 GET
请求地址 http://192.168.3.214:9200/index/_search?q=desc:你好
解析 index 索引名称
_search 表示搜索
q=desc:你好 表示查询desc这个字段里面包含你好的数据

多个查询条件可以在q后面再加一个q=age:22. 例如:?q=desc:你好&q=age:22

DSL的方式查询数据

QueryString的方式查询数据不够灵活,不适用复杂查询。 使用DSL的方式查询更加灵活、方便、支持复杂查询。

使用DSL查询数据方法

名称 备注
请求方式 POST
请求地址 http://192.168.3.214:9200/index/_doc/_search
参数类型 JSON 参数格式见下表

根据字段内容查询数据

根据字段查询数据,如果该字段不支持分词,例如keyword类型的字段,查询的字段内容只是一部分的话,是查不出来数据的。

{
    "query": {
        "match": {
            "desc": "你好"
        }
    }
}

如果要查询同时满足两个词汇都存在的数据,可以使用下面这种方式查询:

{
    "query": {
        "match": {
            "desc": {
                "query": "你好 学习",
                "operator":"and" # 表示要同时满足查询的所有词汇,默认是or,相当于上面的方式查询
            }
        }
    }
}

minimum_should_match, 这个属性表示查询的字符串被分词后,匹配百分之多少词汇的数据。例如查询:今天天气好晴朗,我想出去玩。假设这个句子被分成10个词汇,minimum_should_match参数设置60%(向下取整 ),表示查询的数据中,匹配上6个词汇就会被查询出来。

{
    "query": {
        "match": {
            "desc": {
                "query": "今天天气好晴朗,我想出去玩",
                "minimum_should_match": "60%" 
            }
        }
    }
}

查询索引是否包含某个属性

{
    "query": {
        "exists": {
            "field": "username"
        }
    }
}

查询所有

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

查询部分字段数据

{
    "query": {
        "match_all": {}
    },
    "_source": [
        "id",
        "nickname",
        "age"
    ]
}

分页查询

{
    "query": {
        "match_all": {}
    },
    "_source": [
        "id",
        "nickname",
        "age"
    ],
    "from": 0, # 数据起始位置
    "size": 10 # 每页展示数量
}

根据字段内容模糊匹配

{
    "query": {
        "term": {
            "desc": "你好"
        }
    },
    "_source": [
        "id",
        "nickname",
        "desc"
    ]
}

term 是模糊搜索这个字段内容,只要这个字段内容包含搜索的字符串,就展示出来,match是分词搜索,首先会对搜索的字符串进行分词,然后会检索出所有包含这些分词的数据。

也可以同时查询多个词汇:

{
    "query": {
        "terms": {
            "desc": ["你好", "学习"]
        }
    },
    "_source": [
        "id",
        "nickname",
        "desc"
    ]
}

使用terms是可以支持多个词汇查询,只要包含搜索词汇中的其中一个,就会被检索出来。

根据词条去查询

{
    "query": {
        "match_phrase": {
            "desc": {
                "query": "大学 毕业"
            }
        }
    },
    "_source": [
        "id",
        "nickname",
        "desc"
    ]
}

使用match_phrase查询,首先会对查询的词条进行分词,然后去找这些分词同时在这个字段内容下的数据。上面的例子两个词汇,需要连贯在一起才能查询出来。如果要查询非连贯的词汇,可以使用下面的方式。

{
    "query": {
        "match_phrase": {
            "desc": {
                "query": "大学 毕业",
                "slop": 3 # 这个参数表示大学和毕业中间可以跳过多少个词汇
            }
        }
    },
    "_source": [
        "id",
        "nickname",
        "desc"
    ]
}

指定多个ID查询

{
    "query": {
        "ids": {
            "type": "_doc",
            "values": ["1001", "1002", "1009"]
        }
    },
    "_source": [
        "id",
        "nickname",
        "desc"
    ]
}

在多个字段去查询

{
    "query": {
        "multi_match": {
            "desc": "你好啊",
            "fields": [
                "desc", "nickname^10"
            ]
        }
    }
}

由于默认匹配的词汇越少,分数越低,搜索出来的数据排名会靠下,如果要对某个字段查询出来的数据提升排名,则可以为这个字段设置权重,设置方法见上方:"nickname ^ 10"

布尔查询

{
    "query": {
        "bool": {
            "must": [
                {
                    "multi_match": {
                        "query": "你好",
                        "fields": ["desc", "nickname"]
                    }
                },{
                    "term": {
                        "sex": 0
                    }
                }
            ],
            "should": [
                {
                    "match": {
                       "desc": "我 "
                    }
                }
            ]
        }
    }
}

must: 表示同时满足对应的词汇才会被搜索出来(相当于mysql的AND) must_not: 表示所有词汇都不满足才会被搜索出来 (相当于MySQL的not) should: 表示所有词汇只要满足一个就会被搜索出来(相当于MySQL的or)

有时候我们想把分数较低的词汇排名靠前,可以是boost属性为这个词汇加权,使用方法见下方示例:

{
    "query": {
        "bool": {
            "should": [
                {
                    "match": {
                        "query": "你好",
                        "boost": 2
                    }
                },{
                    "match": {
                        "query": "律师",
                        "boost": 10
                    }
                }
            ]
        }
    }
}

过滤器

过滤器,顾名思义可以在数据集合中过滤出自己想要的数据,比如过滤数据中金额在50~60之间的数据。

{
    "query": {
        "match": {
            "desc": "五子棋游戏"
        }
    },
    "post_filter": {
        "range": {
            "money": {
                "gt": 50,
                "lt": 60
            }
        }
    }
}

上面参数中,post_filter表示过滤的意思,与query平级;range表示范围查询,money是mapping的一个字段。 gt:大于,lt:小于,gte:大于等于,lte:小于等于

排序

{
    "query": {
        "match": {
            "desc": "五子棋游戏"
        }
    },
    "sort": [
        {
            "age": "desc"
        }
    ]
}

支持分词的字段,是不能进行排序的,比如text类型的字段,如果要对这个字段进行排序,可以为这个字段添加一个附属的属性用于排序,可以参考下面创建mapping的例子:

{
    "properties": {
        "id": {
            "type": "long"
        },
        "nickname": {
            "type": "text",
            "analyzer": "ik_max_word",
            "fields": {
                "keyword": { # 这里的keyword,如果下面有text类型的字段需要排序也可以取相同的名字
                    "type": "keyword"
                }
            }
        }
    }
}

创建好可以排序的text类型的字段后,在使用这个字段排序时,需要使用如下方式去排序:

{
    "sort": [
        {
            "nickname.keyword": "desc"
        }
    ]
}

这里的nickname是字段名称,keyword是这个字段的附属属性的名称。

搜索出的数据中匹配的词汇高亮

在我们搜索出来的数据,是根据查询的字符串分词后的词汇匹配出来的,我们可以将这些词汇进行高亮显示。 使用高亮显示的方式如下:

{
    "query": {
        "match": {
            "desc": "五子棋游戏"
        }
    },
    "highlight": { # 高亮显示配置
        "pre_tags": ["<span>"],   # 高亮显示的词汇前置标签
        "post_tags": ["</span>"], # 高亮显示的词汇结束标签
        "fields": {
            "desc": {}  # 高亮显示的字段
        }
    }
}