目录

分布式搜索引擎ES-DSL搜索详解

1.DSL搜索-入门语法

建立索引: xxx(自定义名称)

自定义mapping:

POST /shop/_mapping

java 复制代码
{
    "properties": {
        "id": {
            "type": "long"
        },
        "age": {
            "type": "integer"
        },
        "username": {
            "type": "keyword"
        },
        "nickname": {
            "type": "text",
            "analyzer": "ik_max_word"
        },
        "money": {
            "type": "float"
        },
        "desc": {
            "type": "text",
            "analyzer": "ik_max_word"
        },
        "sex": {
            "type": "byte"
        },
        "birthday": {
            "type": "date"
        },
        "face": {
            "type": "text",
            "index": false
        }
    }
}

请求参数的查询(QueryString)

查询[字段]包含[内容]的文档

测试搜索:

GET /shop/_doc/_search?q=desc:新华网

拼接查询:称为queryString方式查询

GET /shop/_doc/_search?q=nickname:新&q=age:25

text与keyword搜索对比测试(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基本语法

QueryString用的很少,一旦参数复杂就难以构建,所以大多查询都会使用dsl来进行查询更好。

Domain Specific Language

特定领域语言

基于JSON格式的数据查询

查询更灵活,有利于复杂查询

DSL格式语法:

查询

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match": {
            "desc": "新华网"
        }
    }
}

判断某个字段是否存在

java 复制代码
{
    "query": {
        "exists": {
	        "field": "desc"
	    }
    }
}

语法格式为一个json object,内容都是key-value键值对,json可以嵌套。

key可以是一些es的关键字,也可以是某个field字段,后面会遇到

搜索不合法问题定位

DSL查询的时候经常会出现一些错误查询,出现这样的问题大多都是json无法被es解析,他会像java那样报一个异常信息,根据异常信息去推断问题所在,比如json格式不对,关键词不存在未注册等等,甚至有时候不能定位问题直接复制错误信息到百度一搜就能定位问题了。

2.DSL搜索-查询所有与分页

match_all
在索引中查询所有的文档

GET /shop/_doc/_search

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match_all": {}
    },
    "_source": ["id", "nickname", "age"]
}

可视化操作:

分页查询

默认查询是只有10条记录,可以通过分页来展示

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match_all": {}
    },
    "from": 0,
    "size": 10
}
java 复制代码
{
	"query": {
		"match_all": {}
	},
	"_source": [
		"id",
		"nickname",
		"age"
	],
	"from": 5,
	"size": 5
}

Head可视化操作

3.DSL搜索-term与match

term精确搜索与match分词搜索

搜索的时候会把用户搜索内容,比如"中国强大"作为一整个关键词去搜索,而不会对其进行分词后再搜索

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "term": {
            "desc": "新华网"
        }
    }
}

对比

java 复制代码
{
    "query": {
        "match": {
            "desc": "新华网"
        }
    }
}

注:match会对新华网先进行分词(其实就是全文检索),在查询,而term则不会,直接把新华网作为一个整的词汇去搜索。

head 可视化操作对比:

terms 多个词语匹配检索

相当于是tag标签查询,可以完全匹配做类似标签的查询

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "terms": {
            "desc": ["新华网", "学习", "骚年"]
        }
    }
}

4.其他常用语法

(1)match_phrase 短语匹配

match:分词后只要有匹配就返回,match_phrase:分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。(搜索比较严格)

slop:允许词语间跳过的数量

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match_phrase": {
            "desc": {
            	"query": "大学 毕业 研究生",
            	"slop": 2
            }
        }
    }
}

(2)match 扩展

operator

or:搜索内容分词后,只要存在一个词语匹配就展示结果

and:搜索内容分词后,都要满足词语匹配

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match": {
            "desc": "新华网"
        }
    }
}

等同于

java 复制代码
{
    "query": {
        "match": {
            "desc": {
                "query": "xbox游戏机",
                "operator": "or"
            }
        }
    }
}

相当于 select * from shop where desc='xbox' or|and desc='游戏机'

minimum_should_match: 最低匹配精度,至少有[分词后的词语个数]x百分百,得出一个数据值取整。举个例子:当前属性设置为70,若一个用户查询检索内容分词后有10个词语,那么匹配度按照 10x70%=7,则desc中至少需要有7个词语匹配,就展示;若分词后有8个,则 8x70%=5.6,则desc中至少需要有5个词语匹配,就展示。

minimum_should_match 也能设置具体的数字,表示个数

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match": {
            "desc": {
                "query": "好玩的xbox游戏机",
                "minimum_should_match": "60%"
            }
        }
    }
}

根据文档主键ids搜索

GET /shop/_doc/1001

查询多个

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "ids": {
            "type": "_doc",
            "values": ["1001", "1010", "1008"]
        }
    }
}

(3)multi_macth/boost

multi_match

满足使用match在多个字段中进行查询的需求

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "multi_match": {
                "query": "皮特帕克慕课网",
                "fields": ["desc", "nickname"]

        }
    }
}

boost

权重,为某个字段设置权重,权重越高,文档相关性得分就越高。通畅来说搜索商品名称要比商品简介的权重更高。

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "multi_match": {
                "query": "皮特帕克慕课网",
                "fields": ["desc", "nickname^10"]

        }
    }
}

(4)布尔查询

可以组合多重查询

must:查询必须匹配搜索条件,譬如 and

should:查询匹配满足1个以上条件,譬如 or

must_not:不匹配搜索条件,一个都不要满足

实操1:

POST /shop/_doc/_search

java 复制代码
{
    "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
                    }
                }
            ]
        }
    }
}

实操2:

java 复制代码
{
    "query": {
        "bool": {
            "must": [
                {
                	"match": {
                		"desc": "新"
                	}	
                },
                {
                	"match": {
                		"nickname": "新"
                	}	
                }
            ],
            "should": [
                {
                	"match": {
                		"sex": "0"
                	}	
                }
            ],
            "must_not": [
                {
                	"term": {
                		"birthday": "1992-12-24"
                	}	
                }
            ]
        }
    }
}

为指定词语加权

特殊场景下,某些词语可以单独加权,这样可以排得更加靠前。

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "bool": {
            "should": [
            	{
            		"match": {
            			"desc": {
            				"query": "律师",
            				"boost": 18
            			}
            		}
            	},
            	{
            		"match": {
            			"desc": {
            				"query": "进修",
            				"boost": 2
            			}
            		}
            	}
            ]
        }
    }
}

(5)过滤器

对搜索出来的结果进行数据过滤。不会到es库里去搜,不会去计算文档的相关度分数,所以过滤的性能会比较高,过滤器可以和全文搜索结合在一起使用。

post_filter元素是一个顶层元素,只会对搜索结果进行过滤。不会计算数据的匹配度相关性分数,不会根据分数去排序,query则相反,会计算分数,也会按照分数去排序。

使用场景:

query:根据用户搜索条件检索匹配记录

post_filter:用于查询后,对结果数据的筛选

实操:查询账户金额大于80元,小于160元的用户。并且生日在1998-07-14的用户

gte:大于等于

lte:小于等于

gt:大于

lt:小于

(除此以外还能做其他的match等操作也行)

POST /shop/_doc/_search

java 复制代码
{
	"query": {
		"match": {
			"desc": "新华网游戏"
		}	
    },
    "post_filter": {
		"range": {
			"money": {
				"gt": 60,
				"lt": 1000
			}
		}
	}	
}

(6)排序

es的排序同sql,可以desc也可以asc。也支持组合排序。

实操:

POST /shop/_doc/_search

java 复制代码
{
	"query": {
		"match": {
			"desc": "新华网游戏"
		}
    },
    "post_filter": {
    	"range": {
    		"money": {
    			"gt": 55.8,
    			"lte": 155.8
    		}
    	}
    },
    "sort": [
        {
            "age": "desc"
        },
        {
            "money": "desc"
        }
    ]
}

对文本排序

由于文本会被分词,所以往往要去做排序会报错,通常我们可以为这个字段增加额外的一个附属属性,类型为keyword,用于做排序。

创建新的索引

POST /shop2/_mapping

java 复制代码
{
    "properties": {
        "id": {
            "type": "long"
        },
        "nickname": {
            "type": "text",
            "analyzer": "ik_max_word",
            "fields": {
                "keyword": {
                    "type": "keyword"
                }
            }
        }
    }
}

插入数据

POST /shop2/_doc

java 复制代码
{
    "id": 1001,
    "nickname": "美丽的风景"
}
{
    "id": 1002,
    "nickname": "漂亮的小哥哥"
}
{
    "id": 1003,
    "nickname": "飞翔的巨鹰"
}
{
    "id": 1004,
    "nickname": "完美的天空"
}
{
    "id": 1005,
    "nickname": "广阔的海域"
}

排序

java 复制代码
{
    "sort": [
        {
            "nickname.keyword": "desc"
        }
    ]
}

(7)高亮显示

高亮显示

POST /shop/_doc/_search

java 复制代码
{
    "query": {
        "match": {
            "desc": "新华网"
        }
    },
    "highlight": {
        "pre_tags": ["<tag>"],
        "post_tags": ["</tag>"],
        "fields": {
            "desc": {}
        }
    }
}
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
CopyLower37 分钟前
分布式ID生成方案的深度解析与Java实现
java·开发语言·分布式
Charlie__ZS4 小时前
SpringCloud - 分布式事务
分布式·spring·spring cloud
lauo6 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
Hadoop_Liang11 小时前
openEuler24.03 LTS下安装Spark
大数据·分布式·spark·openeuler
ylatin11 小时前
Elasticsearch 索引 es
大数据·linux·elasticsearch
杰克逊的日记12 小时前
es的告警信息
大数据·elasticsearch·搜索引擎
何似在人间57513 小时前
Seata 支持哪些模式的分布式事务?
分布式·mysql·seata·分布式事务
IT成长日记15 小时前
【Hadoop入门】Hadoop生态之Yarn简介
大数据·hadoop·分布式
程序员沉梦听雨15 小时前
Kafka实现延迟消息
分布式·kafka
煤烦恼15 小时前
spark core编程之行动算子、累加器、广播变量
大数据·分布式·spark