Elasticsearch的DSL风格
非DSL风格的查询方式
查询[字段]包含[内容]的文档
# 可以理解为在全文搜索的基础上添加了查询字段的筛选
GET /shop/_doc/_search?q=desc:doudou
GET /shop/_doc/_search?q=nickname:men&q=age:25
text与keyword搜索对比测试(keyword不会被倒排索引,不会被分词)
# 这里nickname中的格式是text而username是keyword
# 如果是text格式的话,会对super hero进行分词;如果是keyword则不会
GET /shop/_doc/_search?q=nickname:super
GET /shop/_doc/_search?q=username:super
GET /shop/_doc/_search?q=username:super hero
以上方式称之为QueryString查询方式,参数都是放在url中作为请求参数的。
DSL基础语法
match和exists
分词匹配和是否存在某字段
# 查询指定字段含有某些词汇
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": "doudou"
}
}
}
# 判断某个字段是否存在
{
"query": {
"exists": {
"field": "desc"
}
}
}
match_all
查询全部和分页
# url方式
GET /shop/_doc/_search
# DSL方式,使用了match_all的关键字
# _source用于指定要展现的字段和select后面接的字段是一致的
POST /shop/_doc/_search
{
"query": {
"match_all": {}
},
"_source": ["id", "nickname", "age"]
}
在header中使用界面的操作
分页查询,默认只有10条记录
# 在query同级下面添加关键字from和size,其中from指记录的下标,size为单页的记录条数
POST /shop/_doc/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 10
}
{
"query": {
"match_all": {}
},
"_source": [
"id",
"nickname",
"age"
],
"from": 5,
"size": 5
}
term
term和match的区别,其实两者都是查询含有指定词汇的字段,但是match会对我们输入的词汇进行再分词,而term就是精确匹配
POST /shop/_doc/_search
{
"query": {
"term": {
"desc": "大学城" # 就直接用大学城查
}
}
}
对比
{
"query": {
"match": {
"desc": "大学城" # 会先对大学城进行分词,eg:大学,城,大...再进行分词
}
}
}
header的操作
terms
多词匹配检索
POST /shop/_doc/_search
{
"query": {
"terms": {
"desc": ["慕课网", "学习", "骚年"] # 默认是or操作
}
}
}
match_phrase
短语匹配
match:分词后只要有匹配就返回,match_phrase:分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。(搜索比较严格)
- slop:允许词语间跳过的数量
POST /shop/_doc/_search
{
"query": {
"match_phrase": {
"desc": {
"query": "大学 毕业 研究生",
"slop": 2 # 允许大学和毕业和研究生之间相隔的词汇少于等于2个,不要求紧挨着
}
}
}
}
operator
match扩展:operator
- and
- or 默认情况下是使用or的
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": "慕课网"
}
}
}
# 等同于
{
"query": {
"match": {
"desc": {
"query": "xbox游戏机",
"operator": "or"
}
}
}
}
# 相当于 select * from shop where desc='xbox' or|and desc='游戏机'
在使用and的时候如果想降低标准可以使用minimum_should_match这个关键词来标记、
- minimum_should_match:
最低匹配精度,至少有[分词后的词语个数]x百分百,得出一个数据值取整。举个例子:当前属性设置为70,若一个用户查询检索内容分词后有10个词语,那么匹配度按照
10x70%=7,则desc中至少需要有7个词语匹配,就展示;若分词后有8个,则
8x70%=5.6,则desc中至少需要有5个词语匹配,就展示。
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": {
"query": "女友生日送我好玩的xbox游戏机",
"minimum_should_match": "60%"
}
}
}
}
ids
根据文档主键进行搜索
# url方式
GET /shop/_doc/1001
# DSL风格
POST /shop/_doc/_search
{
"query": {
"ids": {
"type": "_doc", # 要加一个文档类型,新版只有_doc了
"values": ["1001", "1010", "1008"]
}
}
}
- multi_match满足match的多个匹配方式
# 匹配的词汇会在多个字段中查询
POST /shop/_doc/_search
{
"query": {
"multi_match": {
"query": "皮特帕克慕课网",
"fields": ["desc", "nickname"]
}
}
}
因为显示是根据权重(分数)来排序的,可以通过boost来改变显示顺序
POST /shop/_doc/_search
{
"query": {
"multi_match": {
"query": "皮特帕克慕课网",
"fields": ["desc", "nickname^10"] # 就是这个^符号,现在就以nickname要标准
}
}
}
nickname^10 代表搜索提升10倍相关性,也就是说用户搜索的时候其实以这个nickname为主,desc为辅,nickname的匹配相关度当然要提高权重比例了。
布尔查询
- must 所有条件都必须命中
- must_not 所有条件不能命中
- should 只要满足其中一条就可以了
以上3个关键字可以同时使用,和query都是同级的
POST /shop/_doc/_search
{
"query": {
"bool": { # 使用布尔查询需要先标注这个关键字
"must": [
{
"multi_match": {
"query": "慕课网",
"fields": ["desc", "nickname"]
}
},
{
"term": {
"sex": 1
}
},
{
"term": {
"birthday": "1996-01-14"
}
}
]
}
}
}
{
"query": {
"bool": {
"should(must_not)": [
{
"multi_match": {
"query": "学习",
"fields": ["desc", "nickname"]
}
},
{
"match": {
"desc": "游戏"
}
},
{
"term": {
"sex": 0
}
}
]
}
}
}
POST /shop/_doc/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"desc": "慕"
}
},
{
"match": {
"nickname": "慕"
}
}
],
"should": [
{
"match": {
"sex": "0"
}
}
],
"must_not": [
{
"term": {
"birthday": "1992-12-24"
}
}
]
}
}
}
boost
为指定词语加权
POST /shop/_doc/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"desc": {
"query": "律师",
"boost": 18
}
}
},
{
"match": {
"desc": {
"query": "进修",
"boost": 2
}
}
}
]
}
}
}
post_filter
使用post_filter过滤器,但是这个过滤器是在检索出来的结果上再进行过滤,这样的操作效率会更高,所以其和query是同级的关键字
- gt 大于
- lt 小于
- gte 大于等于
- lte 小于等于
这里还配合了range关键字使用,使用上述关键字前要使用
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": "慕课网游戏"
}
},
"post_filter": {
"range": {
"money": {
"gt": 60,
"lt": 1000
}
}
}
}
sort
排序
和query,post_filter等关键字同级,不能对text数据类型进行排序,如果需要对有text属性的字段排序的话,需要为这个字段添加一个附属属性表明是keyword类型
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": "慕课网游戏"
}
},
"post_filter": {
"range": {
"money": {
"gt": 55.8,
"lte": 155.8
}
}
},
"sort": [ # 后面接的是一个数组
{
"age": "desc"
},
{
"money": "desc"
}
]
}
创建mappings时要主要的添加附属属性
POST /shop2/_mapping
{
"properties": {
"id": {
"type": "long"
},
"nickname": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
使用附属属性进行排序时,注意添加附属属性的名称
{
"sort": [
{
"nickname.keyword": "desc"
}
]
}
highlight
高亮显示
其中pre_tags和post_tags这两个关键字使用用于对要高亮的词语的前后标注
百度使用的是em标签,而阿里使用的是span标签
POST /shop/_doc/_search
{
"query": {
"match": {
"desc": "慕课网"
}
},
"highlight": {
"pre_tags": ["<tag>"],
"post_tags": ["</tag>"],
"fields": {
"desc": {}
}
}
}
prefix
根据前缀前查询
POST /shop/_doc/_search
{
"query": {
"prefix": {
"desc": "imo"
}
}
}
fuzzy
模糊搜索,并不是指的sql的模糊搜索,而是用户在进行搜索的时候的打字错误现象,搜索引擎会自动纠正,然后尝试匹配索引库中的数据。
POST /shop/_doc/_search
{
"query": {
"fuzzy": {
"desc": "imoov.coom"
}
}
}
# 或多字段搜索
{
"query": {
"multi_match": {
"fields": [ "desc", "nickname"],
"query": "imcoc supor",
"fuzziness": "AUTO"
}
}
}
{
"query": {
"multi_match": {
"fields": [ "desc", "nickname"],
"query": "演说",
"fuzziness": "1"
}
}
}
wildcard
占位符查询
- ?:1个字符
- *:1个或多个字符
POST /shop/_doc/_search
{
"query": {
"wildcard": {
"desc": "*oo?"
}
}
}
{
"query": {
"wildcard": {
"desc": "演*"
}
}
}
前缀和占位符两种查询相对于term的精确查询没那么严格,但是和match查询来说其匹配模式更精确一点吧