https://www.elastic.co/guide/en/enterprise-search/current/start.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-match-query.html
Full text Query中,我们只需要把如下的那么多点分为3大类,你的体系能力会大大提升
很多api都可以查得到,我们只要大概知道有支持哪些功能
GET visit_log/_search
{
"query": { "match": {
"serverHostName": "wei"
}},
"sort": [
{ "_id": "asc" }
],
"from": 0,
"size": 10
}
Elasticsearch 执行上面这个 match 查询的步骤是:
1. 检查字段类型 。
标题 title 字段是一个 string 类型( analyzed )已分析的全文字段,这意味着查询字符串本身也应该被分析。
1. 分析查询字符串 。
将查询的字符串 wei cui传入标准分析器中,输出的结果是单个项 wei。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询。
1. 查找匹配文档 。
用 term 查询在倒排索引中查找 wei然后获取一组包含该项的文档,本例的结果是文档:1、2 和 3 。
1. 为每个文档评分 。
用 term 查询计算每个文档相关度评分 _score ,这是种将词频(term frequency,即词 quick 在相关文档的 title 字段中出现的频率)和反向文档频率(inverse document frequency,即词 quick 在所有文档的 title 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。
查询结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "nUL9rokBpGsmR0pP0VSc",
"_score" : null,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 7,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "liu wei",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add7",
"createTime" : 1690446876000
},
"sort" : [
"nUL9rokBpGsmR0pP0VSc"
]
}
]
}
}
查询字段包含wei cui两个词
GET visit_log/_search
{
"query": { "match": {
"serverHostName": "wei cui"
}},
"sort": [
{ "_id": "asc" }
],
"from": 0,
"size": 10
}
结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "TEL9rokBpGsmR0pPXFMo",
"_score" : null,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 5,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "wang cui",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add6",
"createTime" : 1690446876000
},
"sort" : [
"TEL9rokBpGsmR0pPXFMo"
]
},
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "nUL9rokBpGsmR0pP0VSc",
"_score" : null,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 7,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "liu wei",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add7",
"createTime" : 1690446876000
},
"sort" : [
"nUL9rokBpGsmR0pP0VSc"
]
}
]
}
}
因为 match 查询必须查找两个词( [“liu”,“wei”] ),它在内部实际上先执行两次 term 查询,然后将两次查询的结果合并作为最终结果输出。为了做到这点,它将两个 term 查询包入一个 bool 查询中,
所以上述查询的结果,和如下语句查询结果是等同的
GET /visit_log/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"serverHostName": "liu"
}
},
{
"term": {
"serverHostName": "cui"
}
}
]
}
}
}
上面等同于should(任意一个满足),是因为 match还有一个operator参数,默认是or, 所以对应的是should。
GET /visit_log/_search
{
"query": {
"match": {
"serverHostName": {
"query": "wang cui",
"operator": "or"
}
}
}
}
多字段分词
GET /visit_log/_search
{
"query": {
"bool": {
"should": [
{ "match": { "serverHostName": "cui wei" }},
{ "match": { "msgContent": "add3 add4" }}
]
}
}
}
如果用户给定 3 个查询词,想查找至少包含其中 2 个的文档,该如何处理?将 operator 操作符参数设置成 and 或者 or 都是不合适的。
match 查询支持 minimum_should_match 最小匹配参数,这让我们可以指定必须匹配的词项数用来表示一个文档是否相关。我们可以将其设置为某个具体数字,更常用的做法是将其设置为一个百分数,因为我们无法控制用户搜索时输入的单词数量:
GET /visit_log/_search
{
"query": {
"match": {
"serverHostName": {
"query": "wang cui wangcui",
"minimum_should_match": "75%"
}
}
}
}
当然也等同于
GET /visit_log/_search
{
"query": {
"bool": {
"should": [
{ "match": { "serverHostName": "wang" }},
{ "match": { "serverHostName": "cui" }},
{ "match": { "serverHostName": "wangcui" }}
],
"minimum_should_match": 2
}
}
}
那有没有可以查询出quick brown f的方式呢?ELasticSearch在match_phrase基础上提供了一种可以查最后一个词项是前缀的方法,这样就可以查询test es a了
GET /visit_log/_search
{
"query": {
"match_phrase_prefix": {
"msgContent": {
"query": "test es a"
}
}
}
}
(ps: prefix的意思不是整个text的开始匹配,而是最后一个词项满足term的prefix查询而已)
GET /visit_log/_search
{
"query": {
"match_bool_prefix": {
"msgContent": {
"query": "es test a"
}
}
}
}
所以这样你就能理解,match_bool_prefix查询中的quick,brown,f是无序的。
GET /visit_log/_search
{
"query": {
"multi_match" : {
"query": "add7 wang",
"fields": [ "msgContent", "*HostName" ]
}
}
}
结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.7917595,
"hits" : [
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "nUL9rokBpGsmR0pP0VSc",
"_score" : 1.7917595,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 7,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "liu wei",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add7",
"createTime" : 1690446876000
}
},
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "TEL9rokBpGsmR0pPXFMo",
"_score" : 1.0800905,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 5,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "wang cui",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add6",
"createTime" : 1690446876000
}
},
{
"_index" : "visit_log",
"_type" : "_doc",
"_id" : "6UL9rokBpGsmR0pPjVOS",
"_score" : 1.0800905,
"_source" : {
"_class" : "org.lwd.microservice.boot.es.entity.VisitLog",
"id" : 6,
"tableName" : "VisitLog",
"userLoginId" : 3,
"serverIpAddress" : "127.0.0.1",
"serverHostName" : "wang ting",
"initialRequest" : "http://localhost:8023",
"msgContent" : "test es add6",
"createTime" : 1690446876000
}
}
]
}
}
*表示前缀匹配字段。
此查询使用语法根据运算符(例如AND或)来解析和拆分提供的查询字符串NOT。然后查询在返回匹配的文档之前独立分析每个拆分的文本。
可以使用该query_string查询创建一个复杂的搜索,其中包括通配符,跨多个字段的搜索等等。尽管用途广泛,但查询是严格的,如果查询字符串包含任何无效语法,则返回错误。
例如:
GET /visit_log/_search
{
"query": {
"query_string": {
"query": "(wangcui) OR (add6)",
"fields": [ "msgContent", "*HostName" ]
}
}
}
Intervals是时间间隔的意思,本质上将多个规则按照顺序匹配。
GET /visit_log/_search
{
"query": {
"intervals" : {
"msgContent" : {
"all_of" : {
"ordered" : true,
"intervals" : [
{
"match" : {
"query" : "liu",
"max_gaps" : 0,
"ordered" : true
}
},
{
"any_of" : {
"intervals" : [
{ "match" : { "query" : "es" } },
{ "match" : { "query" : "add6" } }
]
}
}
]
}
}
}
}
}
因为interval之间是可以组合的,所以它可以表现的很复杂
自行查官方文档,有可能后边会出详解
自行查官方文档,有可能后边会出详解
自行查官方文档,有可能后边会出详解
自行查官方文档,有可能后边会出详解
原创不易,如若本文能够帮助到您的同学
支持我:关注我+点赞+收藏⭐️
留言:探讨问题,看到立马回复
格言:己所不欲勿施于人 扬帆起航、游历人生、永不言弃!