Elasticsearch从入门到精通-05ES匹配查询

Elasticsearch从入门到精通-05ES匹配查询

👏作者简介:大家好,我是程序员行走的鱼

📖 本篇主要介绍和大家一块学习一下ES各种场景下的匹配查询,有助于我们在项目中进行综合使用

前提

创建索引并指定ik分词器:

PUT /es_db
{
  "settings": {
    "index": {
      "analysis.analyzer.default.type": "ik_max_word"
    }
  }
}

添加数据:

PUT /es_db/_doc/1
{
  "name": "张三",
  "sex": 1,
  "age": 25,
  "address": "广州天河公园",
  "remark": "java developer"
}

PUT /es_db/_doc/2
{
  "name": "李四",
  "sex": 1,
  "age": 28,
  "address": "广州荔湾大厦",
  "remark": "java assistant"
}

PUT /es_db/_doc/3
{
  "name": "rod",
  "sex": 0,
  "age": 26,
  "address": "广州白云山公园",
  "remark": "php developer"
}

PUT /es_db/_doc/4
{
  "name": "admin",
  "sex": 0,
  "age": 22,
  "address": "长沙橘子洲头",
  "remark": "python assistant"
}

PUT /es_db/_doc/5
{
  "name": "小明",
  "sex": 0,
  "age": 19,
  "address": "长沙岳麓山",
  "remark": "java architect assistant"
}		

案例1:字段包含关键词中几个

需要搜索的document中的remark字段包含java和developer词组

operator实现

GET /es_db/_search
{
  "query": {
    "match": {
      "remark": {
        "query": "java developer",
        "operator": "and"
      }
    }
  }
}

image-20240314202432753

上述语法中,如果将operator的值改为or。则与remark": "java developer"等价 。默认的ES执行搜索的时候,operator就是or。如果在搜索的结果document中,需要remark字段中包含多个搜索词条中的一定比例,可以使用下述语法实现搜索。其中minimum_should_match可以使用百分比或固定数字。百分比代表query搜索条件中词条百分比,如果无法整除,向下匹配(如,query条件有3个单词,如果使用百分比提供精准度计算,那么是无法除尽的,如果需要至少匹配两个单词,则需要用67%来进行描述。如果使用66%描述,ES则认为匹配一个单词即可。)。固定数字代表query搜索条件中的词条,至少需要匹配多少个。

minimum_should_match实现

完全匹配上:

GET /es_db/_search
{
  "query": {
    "match": {
      "remark": {
        "query": "java architect assistant",
        "minimum_should_match": "100%"
      }
    }
  }
}

image-20240314202754437

至少匹配两个:

GET /es_db/_search
{
  "query": {
    "match": {
      "remark": {
        "query": "java architect assistant",
        "minimum_should_match": "68%"
      }
    }
  }
}

image-20240314202732204

bool+should实现

如果使用should+bool搜索的话,也可以控制搜索条件的匹配度。具体如下:下述案例代表搜索的document中的remark字段中,必须匹配java、developer、assistant三个词条中的至少2个。

GET /es_db/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "remark": "java"
          }
        },
        {
          "match": {
            "remark": "developer"
          }
        },
        {
          "match": {
            "remark": "assistant"
          }
        }
      ],
      "minimum_should_match": 2
    }
  }
}

image-20240314202856726

match的底层转换

其实在ES中,执行match搜索的时候,ES底层通常都会对搜索条件进行底层转换,来实现最终的搜索结果。如:
1.

GET /es_db/_search
{
  "query": {
    "match": {
      "remark": "java developer"
    }
  }
}

转化后:

//转换后是:
GET /es_db/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "remark": "java"
          }
        },
        {
          "term": {
            "remark": {
              "value": "developer"
            }
          }
        }
      ]
    }
  }
}
GET /es_db/_search
{
  "query": {
    "match": {
      "remark": {
        "query": "java developer",
        "operator": "and"
      }
    }
  }
}

转换后:

GET /es_db/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "remark": "java"
          }
        },
        {
          "term": {
            "remark": {
              "value": "developer"
            }
          }
        }
      ]
    }
  }
}
GET /es_db/_search
{
  "query": {
    "match": {
      "remark": {
        "query": "java architect assistant",
        "minimum_should_match": "68%"
      }
    }
  }
}

转换后:

GET /es_db/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "remark": "java"
          }
        },
        {
          "term": {
            "remark": "architect"
          }
        },
        {
          "term": {
            "remark": "assistant"
          }
        }
      ],
      "minimum_should_match": 2
    }
  }
}

建议,如果不怕麻烦,尽量使用转换后的语法执行搜索,效率更高。如果开发周期短,工作量大,使用简化的写法。

案例2:boost权重控制

一般用于搜索时相关度排序使用。如:电商中的综合排序。将一个商品的销量,广告投放,评价值,库存,单价比较综合排序。在上述的排序元素中,广告投放权重最高,库存权重最低,这样权重越大的排序越考前,我们以一下例子为例来详细学习权重的作用。

搜索document中remark字段中包含java的数据,如果remark中包含developer或architect,则包含architect的document优先显示。(就是将architect数据匹配时的相关度分数增加)。

GET /es_db/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "remark": "java"
          }
        }
      ],
      "should": [
        {
          "match": {
            "remark": {
              "query": "developer",
              "boost": 1
            }
          }
        },
        {
          "match": {
            "remark": {
              "query": "architect",
              "boost": 3
            }
          }
        }
      ]
    }
  }
}

image-20240314204501430

在搜索所有remark包含java文档中,我们设置包含architect的权重比包含developer权重大,所以排序后会出现以上的结果,如果我们把developer权重调为比architect权重大,那么developer的排序会比architect高

image-20240314204704668

案例3:基于dis_max实现best fields策略进行多字段搜索

best fields策略: 搜索到的结果,应该是某一个field中匹配到了尽可能多的关键词,被排在前面;而不是尽可能多的field匹配到了少数的关键词,排在了前面.

dis_max语法:直接取多个query中,分数最高的那一个query的分数即可,下边以案例解释这句话的意思

数据准备

PUT /forum
{ "settings" : { "number_of_shards" : 1 }}
POST /forum/article/_bulk
{"index":{"_id":1}}
{"title":"this is java and elasticsearch blog","content":"i like to write best elasticsearch article"}
{"index":{"_id":2}}
{"title":"this is java blog","content":"i think java is the best programming language"}
{"index":{"_id":3}}
{"title":"this is elasticsearch blog","content":"i am only an elasticsearch beginner"}
{"index":{"_id":4}}
{"title":"this is java, elasticsearch, hadoop blog","content":"elasticsearch and hadoop are all very good solution, i am a beginner"}
{"index":{"_id":5}}
{"title":"this is spark blog","content":"spark is best big data solution based on scala ,an programming language similar to java"}

普通DSL:

GET /forum/article/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "java solution"
          }
        },
        {
          "match": {
            "content": "java solution"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

image-20240314231755897

来分析一下结果

计算每个document的relevance score:每个query的分数,乘以matched query数量,除以总query数量

image-20240314231820585

算一下doc2的分数:

{ “match”: { “title”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数 1.1

{ “match”: { “content”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数 1.2

假设分数如下 , 所以是两个分数加起来,比如说,1.1 + 1.2 = 2.3

matched query数量 = 2

总query数量 = 2

2.3 * 2 / 2 = 2.3 当前文档获取分数就是2.1

算一下doc5的分数

image-20240314232029530

{ “match”: { “title”: “java solution” }}:针对文档5,没有关键字匹配,所以没有分数

{ “match”: { “content”: “java solution” }}:针对文档5,java匹配上了,可以得到一个分数2.3

所以说,只有一个query是有分数的,比如2.3 matched query数量 = 1 总query数量 = 2

2.3 * 1 / 2 = 1.15

doc5的分数 = 1.15 < doc2的分数 = 2.3

id=2的数据排在了前面,其实我们希望id=5的排在前面,毕竟id=5的数据 content字段既有java又有solution. 那看下dis_max吧

image-20240314232204456

我们再来计算下两个文档的分数:

{ “match”: { “title”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数1.1

{ “match”: { “content”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数1.2

取最大分数,1.2

{ “match”: { “title”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数0

{ “match”: { “content”: “java solution” }}:针对文档2,java匹配上了,可以得到一个分数2.3

取最大分数,2.3

然后doc2的分数 = 1.2 < doc5的分数 = 2.3,所以doc5就可以排在更前面的地方.

dis_max优点:精确匹配的数据可以尽可能的排列在最前端,且可以通过minimum_should_match来去除长尾数据,避免长尾数据字段对排序结果的影响

长尾数据比如说我们搜索4个关键词,但很多文档只匹配1个,也显示出来了,这些文档其实不是我们想要的,这时候我们就需要对dis_max改进一下:

比如我们查询content中必须包含java solution的文档

GET /forum/article/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {
          "match": {
            "title": "java solution"
          }
        },
        {
          "match": {
            "content": {
               "query": "java solution",
              "minimum_should_match": "100%"
            }
          }
        }
      ]
    }
  }
}

image-20240314210917512

案例4:基于tie_breaker参数优化dis_max搜索效果

dis_max是将多个搜索query条件中相关度分数最高的用于结果排序,忽略其他query分数,在某些情况下,可能还需要其他query条件中的相关度介入最终的结果排序,这个时候可以使用tie_breaker参数来优化dis_max搜索。tie_breaker参数代表的含义是:将其他query搜索条件的相关度分数乘以参数值,再参与到结果排序中。如果不定义此参数,相当于参数值为0。所以其他query条件的相关度分数被忽略。

GET /forum/article/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {
          "match": {
            "title": "java beginner"
          }
        },
        {
          "match": {
            "content":"java beginner"}
          
        }
      ],
       "tie_breaker": 0.5
    }
  }
}

image-20240314233619264

可以明显看出来,文档5直接排序来到了最后一位,因为其他query也参与了计算,综合算起来是score是低于其他文档的。

案例5:使用multi_match简化dis_max+tie_breaker

GET /forum/article/_search
{
  "query": {
    "multi_match": {
      "query": "best java solution",
      "fields": [
        "title",
        "content^2"#^n代表权重,说明如果content匹配到多个关键字的话权重高一点。
      ],
      "type": "best_fields",
      "tie_breaker": 0.5,
      "minimum_should_match": "50%"
    }
  }
}

image-20240314234330295

如果需要的结果是有特殊要求,如:hello world必须是一个完整的短语,不可分割;或document中的field内,包含的hello和world单词,且两个单词之间离的越近,相关度分数越高。那么这种特殊要求的搜索就是近似搜索。包括hell搜索条件在hello world数据中搜索,包括h搜索提示等都数据近似搜索的一部分。下边的案例都是近似匹配的情况

案例6:短语搜索

短语搜索。就是搜索条件不分词,代表搜索条件不可分割。如果java assistant是一个不可分割的短语,我们可以使用前文学过的短语搜索match phrase来实现。语法如下:

GET _search
{
  "query": {
    "match_phrase": {
      "remark": "java assistant"
    }
  }
}

image-20240315084940051

ES是如何实现match phrase短语搜索的?其实在ES中,使用match phrase做搜索的时候,也是和match类似,首先对搜索条件进行分词-analyze。将搜索条件拆分成java和assistant。既然是分词后再搜索,ES是如何实现短语搜索的?

这里涉及到了倒排索引的建立过程。在倒排索引建立的时候,ES会先对document数据进行分词,如:

image-20240315085101565

从上述结果中,可以看到。ES在做分词的时候,除了将数据切分外,还会保留一个position。position代表的是这个词在整个数据中的下标。当ES执行match phrase搜索的时候,首先将搜索条件hello world分词为hello和world。然后在倒排索引中检索数据,如果hello和world都在某个document的某个field出现时,那么检查这两个匹配到的单词的position是否是连续的,如果是连续的,代表匹配成功,如果是不连续的,则匹配失败。

案例7:match phrase优化

在做搜索的时候,如果搜索参数是hello spark。而ES中存储的数据是hello world, java spark。那么使用match phrase则无法搜索到。在这个时候,可以使用match来解决这个问题。但是,当我们需要在搜索的结果中,做一个特殊的要求:hello和spark两个单词距离越近,document在结果集合中排序越靠前,这个时候再使用match则未必能得到想要的结果.针对这种情况,在ES的搜索中,对match phrase提供了参数slop。slop代表match phrase短语搜索的时候,单词最多移动多少次,可以实现数据匹配。在所有匹配结果中,多个单词距离越近,相关度评分越高,排序越靠前。这种使用slop参数的match phrase搜索,就称为近似匹配(proximity search)

举例:

数据为:hello world, java spark

搜索为:match phrase : hello spark。

slop为: 3 (代表单词最多移动3次。)

执行短语搜索的时候,将条件hello spark分词为hello和spark两个单词。并且连续。

接下来,可以根据slop参数执行单词的移动。

下标 : 0 1 2 3

doc : hello world java spark

搜索 : hello spark

移动1: hello spark

移动2: hello spark

匹配成功,不需要移动第三次即可匹配。

再如:

数据为: hello world, java spark

搜索为: match phrase : spark hello。

slop为: 5 (代表单词最多移动5次。)

执行短语搜索的时候,将条件hello spark分词为hello和spark两个单词。并且连续。

接下来,可以根据slop参数执行单词的移动。

下标 : 0 1 2 3

doc : hello world java spark

搜索 : spark hello

移动1: spark/hello

移动2: hello spark

移动3: hello spark

移动4: hello spark

匹配成功,不需要移动第五次即可匹配。

如果当slop移动次数使用完毕,还没有匹配成功,则无搜索结果。如果使用中文分词,则移动次数更加复杂,因为中文词语有重叠情况,很难计算具体次数,需要多次尝试才行。

英语测试:

image-20240315085720061

GET _analyze
{
  "text": "hello world, java spark",
  "analyzer": "standard"
}

POST /test_a/_doc/3
{
  "f": "hello world, java spark"
}

GET /test_a/_search
{
  "query": {
    "match_phrase": {
      "f": {
        "query": "hello spark",
        "slop": 2
      }
    }
  }
}

中文测试:

DELETE /test_a
GET _analyze
{
  "text": "中国,一个世界上最强的国",
  "analyzer": "ik_max_word"
}
PUT /test_a
{
  "settings": {
    "index": {
      "analysis.analyzer.default.type": "ik_max_word"
    }
  }
}
POST /test_a/_doc/3
{
  "f": "中国,一个世界上最强的国家"
}

只移动五次:

image-20240315090026070

移动100次:

image-20240315090052790

案例8:前缀搜索

使用前缀匹配实现搜索能力。通常针对keyword类型字段,也就是不分词的字段。

当然,我们也可以对非keywork类型的字段进行前缀搜索,只需要在字段后边加上.keyword即可

GET /es_db/_search
{
  "query": {
    "prefix": {
      "address.keyword": {
        "value": "广州"
      }
    }
  }
}

image-20240316224001333

前缀搜索效率比较低,前缀搜索不会计算相关度分数。前缀越短,效率越低。如果使用前缀搜索,建议使用长前缀。因为前缀搜索需要扫描完整的索引内容,所

以前缀越长,相对效率越高。

使用match和proximity search实现召回率和精准度平衡。

召回率:召回率就是搜索结果比率,如:索引A中有100个document,搜索时返回多少个document,就是召回率(recall)。

精准度:就是搜索结果的准确率,如:搜索条件为hello java,在搜索结果中尽可能让短语匹配和hello java离的近的结果排序靠前,就是精准度

(precision)。

如果在搜索的时候,只使用match phrase语法,会导致召回率底下,因为搜索结果中必须包含短语(包括proximity search)。

如果在搜索的时候,只使用match语法,会导致精准度底下,因为搜索结果排序是根据相关度分数算法计算得到。

那么如果需要在结果中兼顾召回率和精准度的时候,就需要将match和proximity search混合使用,来得到搜索结果。

案例9:通配符搜索

ES中也有通配符,但是和java还有数据库不太一样,通配符可以在倒排索引中使用,也可以在keyword类型字段中使用。

常用通配符:

  • ? : 一个任意字符
  • * :0~n个任意字符
GET /es_db/_search
{
  "query": {
    "wildcard": {
      "remark": {
        "value": "d*"
      }
    }
  }
}

image-20240316224816970

性能很低,需要扫描完整的索引。

案例10:正则搜索

ES支持正则表达式,可以在倒排索引或keyword类型字段中使用。

常用符号:

  • [] : 范围,如: [0-9]是0~9的范围数字

  • . : 一个字符

+ - 前面的表达式可以出现多次。

GET /es_db/_search
{
  "query": {
    "regexp": {
      "remark": {
        "value": "[a-a].+"
      }
    }
  }
}

image-20240316225055862

性能很低,需要扫描完整索引。

案例11:即时搜索

搜索推荐: search as your type, 搜索提示。如:索引中有若干数据,以“hello”开头,那么在输入hello的时候,推荐相关信息。(类似百度输入框)

image-20240316225327968

其原理和match phrase类似,是先使用match匹配term数据(java),然后在指定的slop移动次数范围内,前缀匹配(d),max_expansions是用于指定prefix

最多匹配多少个term(单词),超过这个数量就不再匹配了。这种语法的限制是,只有最后一个term会执行前缀搜索,执行性能很差,毕竟最后一个term是需要扫描所有符合slop要求的倒排索引的term,因为效率较低,如果必须使用,则一定要使用参数max_expansions。

案例12:模糊搜索技术

搜索的时候,可能搜索条件文本输入错误,如:hello world -> hello word。这种拼写错误还是很常见的。fuzzy技术就是用于解决错误拼写的(在英文中很有效,在中文中几乎无效。),其中fuzziness代表value的值word可以修改多少个字母来进行拼写错误的纠正(修改字母的数量包含字母变更,增加或减少字)。

GET /es_db/_search
{
  "query": {
    "fuzzy": {
      "remark": {
        "value": "jva",
        "fuzziness": 1
      }
    }
  }
}

image-20240316230350735

案例13:高亮查询

image-20240317115237440

在搜索中,经常需要对搜索关键字做高亮显示,高亮显示也有其常用的参数,在这个案例中做一些常用参数的介绍。

highlight简单使用

数据准备:

PUT /news_website
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

PUT /news_website/_doc/1
{
  "title": "我的第一篇文章",
  "content": "大家好,这是我写的第一篇文章,特别喜欢这个文章门户网站!!!"
}

高亮显示:

GET /news_website/_doc/_search
{
  "query": {
    "match": {
      "content": "文章"
    }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}

image-20240317115518040

会变成红色,所以说你的指定的field中,如果包含了那个搜索词的话,就会在那个field的文本中,对搜索词进行红色的高亮显示。

highlight中要高亮的字段和要查询的字段是要进行一一匹配的,比如如果我们也想title中关键字做高亮显示可以这样做:

GET /news_website/_doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "文章"
          }
        },
        {
          "match": {
            "content": "文章"
          }
        }
      ]
    }
  },
  "highlight": {
    "fields": {
      "title": {},
      "content": {}
    }
  }
}

image-20240317115813236

highlight类型

在es中支持好几种highlight

  • plain highlight(lucene highlight):默认
  • posting highlight:性能比plain highlight要高,因为不需要重新对高亮文本进行分词,对磁盘消耗低。
  • fast vector highlight:对大field而言(大于1mb),性能更高

我们看看其他两种的使用方式:

posting highlight:在mappering中设置 "index_options": "offsets"

DELETE news_website
PUT /news_website
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "index_options": "offsets"
      }
    }
  }
}

PUT /news_website/_doc/1
{
  "title": "我的第一篇文章",
  "content": "大家好,这是我写的第一篇文章,特别喜欢这个文章门户网站!!!"
}

image-20240317120108886

GET /news_website/_doc/_search
{
  "query": {
    "match": {
      "content": "文章"
    }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}

image-20240317120157867

fast vector highlight:在mappings中设置"term_vector": "with_positions_offsets"

DELETE /news_website

PUT /news_website
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "term_vector": "with_positions_offsets"
      }
    }
  }
}

image-20240317120321500

指定highlight

当然,如果我们在映射中指定了highlight,但是我们想要查询的时候也指定highlight,那么可以这样查询

GET /news_website/_doc/_search
{
  "query": {
    "match": {
      "content": "文章"
    }
  },
  "highlight": {
    "fields": {
      "content": {
        "type": "plain"
      }
    }
  }
}

image-20240317120733450

设置highlight标签

我们高亮的标签默认是是标签,我们可以通过属性修改高亮标签

  • pre_tags:前置标签
  • post_tags:后置标签
GET /news_website/_doc/_search
{
  "query": {
    "match": {
      "content": "文章"
    }
  },
  "highlight": {
    "pre_tags": [
      "<span color='red'>"
    ],
    "post_tags": [
      "</span>"
    ],
    "fields": {
      "content": {
        "type": "plain"
      }
    }
  }
}

image-20240317120935357

##高亮片段fragment显示

有时候如果我们的内容特别多,不可能所有关键字都高亮显示,那么我们就可以指定片段数量和文本长度。

  • fragment_size: 一个Field的值,比如有长度是1万,但是你不可能在页面上显示这么长,我们可以设置要显示出来的fragment文本判断的长度,默认是100

  • number_of_fragments:可能你的高亮的fragment文本片段有多个片段,你可以指定就显示几个片段

GET /_search
{
  "query": {
    "match": {
      "content": "文章"
    }
  },
  "highlight": {
    "fields": {
      "content": {
        "fragment_size": 10,
        "number_of_fragments": 1
      }
    }
  }
}

image-20240317121246037

案例14:CrossFields 多字段搜索策略

数据准备:

POST /testcross/_bulk
{"index":{"_id": 1}}
{"empId" : "111","name" : "员工1","age" : 20,"sex" : "男","mobile" : "19000001111","salary":1333,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"光谷大道","address":"湖北省武汉市洪山区光谷大厦","content" : "i like to write best elasticsearch article"}
{"index":{"_id": 2}}
{"empId" : "222","name" : "员工2","age" : 25,"sex" : "男","mobile" : "19000002222","salary":15963,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i think java is the best programming language"}
{"index":{"_id": 3}}
{ "empId" : "333","name" : "员工3","age" : 30,"sex" : "男","mobile" : "19000003333","salary":20000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"经济技术开发区","address" : "湖北省武汉市经济开发区","content" : "i am only an elasticsearch beginner"}
{"index":{"_id": 4}}
{"empId" : "444","name" : "员工4","age" : 20,"sex" : "女","mobile" : "19000004444","salary":5600,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"沌口开发区","address" : "湖北省武汉市沌口开发区","content" : "elasticsearch and hadoop are all very good solution, i am a beginner"}
{"index":{"_id": 5}}
{ "empId" : "555","name" : "员工5","age" : 20,"sex" : "男","mobile" : "19000005555","salary":9665,"deptName" : "测试部","provice" : "湖北省","city":"高新开发区","area":"武汉","address" : "湖北省武汉市东湖隧道","content" : "spark is best big data solution based on scala ,an programming language similar to java"}
{"index":{"_id": 6}}
{"empId" : "666","name" : "员工6","age" : 30,"sex" : "女","mobile" : "19000006666","salary":30000,"deptName" : "技术部","provice" : "武汉市","city":"湖北省","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i like java developer"}
{"index":{"_id": 7}}
{"empId" : "777","name" : "员工7","age" : 60,"sex" : "女","mobile" : "19000007777","salary":52130,"deptName" : "测试部","provice" : "湖北省","city":"黄冈市","area":"边城区","address" : "湖北省黄冈市边城区","content" : "i like elasticsearch developer"}
{"index":{"_id": 8}}
{"empId" : "888","name" : "员工8","age" : 19,"sex" : "女","mobile" : "19000008888","salary":60000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"汉阳区","address" : "湖北省武汉市江汉大学","content" : "i like spark language"}
{"index":{"_id": 9}}
{"empId" : "999","name" : "员工9","age" : 40,"sex" : "男","mobile" : "19000009999","salary":23000,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市郑州大学","content" : "i like java developer"}
{"index":{"_id": 10}}
{"empId" : "101010","name" : "张湖北","age" : 35,"sex" : "男","mobile" : "19000001010","salary":18000,"deptName" : "测试部","provice" : "湖北省","city":"武汉","area":"高新开发区","address" : "湖北省武汉市东湖高新","content" : "i like java developer i also like  elasticsearch"}
{"index":{"_id": 11}}
{"empId" : "111111","name" : "王河南","age" : 61,"sex" : "男","mobile" : "19000001011","salary":10000,"deptName" : "销售部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am not like  java "}
{"index":{"_id": 12}}
{"empId" : "121212","name" : "张大学","age" : 26,"sex" : "女","mobile" : "19000001012","salary":1321,"deptName" : "测试部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am java developer  thing java is good"}
{"index":{"_id": 13}}
{"empId" : "131313","name" : "李江汉","age" : 36,"sex" : "男","mobile" : "19000001013","salary":1125,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市二七区","content" : "i like java and java is very best i like it do you like java "}
{"index":{"_id": 14}}
{"empId" : "141414","name" : "王技术","age" : 45,"sex" : "女","mobile" : "19000001014","salary":6222,"deptName" : "测试部",,"provice" : "河南省","city":"郑州市","area":"金水区","address" : "河南省郑州市金水区","content" : "i like c++"}
{"index":{"_id": 15}}
{"empId" : "151515","name" : "张测试","age" : 18,"sex" : "男","mobile" : "19000001015","salary":20000,"deptName" : "技术部",,"provice" : "河南省","city":"郑州市","area":"高新开发区","address" : "河南省郑州高新开发区","content" : "i think spark is good"}

地址存储的时候 不能直接存储 ”湖北省武汉市东湖高新区“ 这样的字符串,一个完整的地址需要用多个字段来唯一标识,一般存储的时候 省/市/区 分别是"provice", “city”, "area"三个字段,那我搜寻湖北省武汉市江汉区这个完整地址 的时候,会如何查询 provice=”湖北省“ , city=“武汉市” , area=“东湖高新” ?
我们可以使用most fields试下:

image-20240317124033250

image-20240317124056261

从结果来看:

  • 不支持 operator=AND,没有一个doc可以match到,因为你的关键字是分布在多个字段中的用了and就是 provice包含湖北省武汉市江汉区或者city包含这三个词,后者 area包含这三个词, 没有一个doc能匹配,因为字段是打散的.
  • 如果用 operator = OR 出来几十条, 从语义上也是错误的, 会把所有包含湖北省,武汉市都搜出来,因为OR操作就是任一字段匹配,就会大量重复无用数据 比如出现 湖北省 XX市 XX区 的数据,甚至是 河南省 郑州市 江汉区的类似数据.
  • 搜索不准确,因为MostFields 会把多个词计算权重后参与最终分计算,累加求和,这就导致如果 有个 郑州市的江汉区,他的权重较高,然后会影响到 湖北省武汉市东湖高 的排序,比他会优先排序

也有人会想,我们直接使用组合查询,provice、city、area三个进行must匹配不就可以查询出来了吗,就如下边的效果:

get /testcross/_search
{
  "query":{
    "bool": {
      "must": [
        {
          "match_phrase": {
            "provice": "湖北省"
          }
        },
        {
          "match_phrase": {
            "city": "武汉"
          }
        },
        {
          "match_phrase": {
            "area": "高新开发区"
          }
        }
      ]
    }
  }
}

image-20240317124515151

似乎没什么问题, 但是正常我们的搜索,很多时候我是不知道他是具体什么字段的,比如我只知道 省/市/区 这三个ABC字段中包含了 湖北省,武汉,高新开发区的查询字段, 就给我命中返回,我不关心哪个字段匹配上,只要三个字段都存在就行
到底是 A:湖北省 B:武汉 C:高新开发区
还是 A:武汉 B:湖北省,C:高新开发区
还是 A:湖北省, B:高新开发区,C:武汉
所以And也是不满足的

基于这种情况,我们可以使用词条为中心的CrossFields 搜索,我们可以实现当我们不关系具体哪些字段,我们只需要将多个field的信息整合成一个作为唯一标识返回即可。

get /testcross/_search
{
  "query":{
    "multi_match": {
      "query": "湖北省 武汉 高新开发区",
      "fields": ["provice","city","area"],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

image-20240317124819625

CrossFields 提高权重控制排名

可以查看刚才CrossFields的查询结果

员工分数
员工108.200133
员工56.558913

如果 provice, city 及area 每个词的权重不同, 比如想要把city权重放的更高点,让权重优先的更考前的返回,我们可以直接在fields中计入权重计算, 可以看到 city 被我改成了 city ^ 2 就是权重扩大 2倍,默认都是1倍

image-20240317125104685

city:高新开发区的被提前了 ,因为 city:武汉 有很多个文档,但是city:高新开发区的就只有几个,所以 TFIDF模型认为 高新开发区 的权重在city字段上更有代表性,所以权重更大,这就影响了结果的排序.

案例15:CopyTo字段组合实现逻辑多字段搜索

场景:

淘宝中搜手机,点击搜索,那么一个商品有很多属性,比如 商品名称,商品卖点,商品描述,商品评价等等等,那么如果搜索手机关键字,并且一个搜索条件都没限定,那底层到底是在那几个字段内进行匹配
如果仅用单一的字段比如名称字段来匹配,很有可能不是用户要的结果,如果使用全字段匹配?这样明显也不合适,比如商品价格,商品库存,商品店铺等,不包含手机信息,那么如何实现?

解决办法:

  • copy_to:就是将多个字段,复制到一个字段中,来实现多字段组合查询,用于解决搜索条件默认字段信息
  • copy_to需要在创建mapping结构的时候就指定 需要将当前字段 copy_to 到哪个字段上,默认搜索条件生效的字段就是你要复制到的字段

准备数据:

注意:

put /testcopy

PUT /testcopy/_mapping
{
        "properties" : {
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "copy_to":"info"
        },
        "age" : {
          "type" : "long"
        },
        "area" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "content" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "deptName" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
          "copy_to":"info"
        },
        "empId" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "mobile" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
         "copy_to":"info"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          },
           "copy_to":"info"
        },
        "provice" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "salary" : {
          "type" : "long"
        },
        "sex" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
  
}


POST /testcopy/_bulk
{"index":{"_id": 1}}
{"empId" : "111","name" : "员工1","age" : 20,"sex" : "男","mobile" : "19000001111","salary":1333,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"光谷大道","address":"湖北省武汉市洪山区光谷大厦","content" : "i like to write best elasticsearch article"}
{"index":{"_id": 2}}
{"empId" : "222","name" : "员工2","age" : 25,"sex" : "男","mobile" : "19000002222","salary":15963,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i think java is the best programming language"}
{"index":{"_id": 3}}
{ "empId" : "333","name" : "员工3","age" : 30,"sex" : "男","mobile" : "19000003333","salary":20000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"经济技术开发区","address" : "湖北省武汉市经济开发区","content" : "i am only an elasticsearch beginner"}
{"index":{"_id": 4}}
{"empId" : "444","name" : "员工4","age" : 20,"sex" : "女","mobile" : "19000004444","salary":5600,"deptName" : "销售部","provice" : "湖北省","city":"武汉","area":"沌口开发区","address" : "湖北省武汉市沌口开发区","content" : "elasticsearch and hadoop are all very good solution, i am a beginner"}
{"index":{"_id": 5}}
{ "empId" : "555","name" : "员工5","age" : 20,"sex" : "男","mobile" : "19000005555","salary":9665,"deptName" : "测试部","provice" : "湖北省","city":"高新开发区","area":"武汉","address" : "湖北省武汉市东湖隧道","content" : "spark is best big data solution based on scala ,an programming language similar to java"}
{"index":{"_id": 6}}
{"empId" : "666","name" : "员工6","age" : 30,"sex" : "女","mobile" : "19000006666","salary":30000,"deptName" : "技术部","provice" : "武汉市","city":"湖北省","area":"江汉区","address" : "湖北省武汉市江汉路","content" : "i like java developer"}
{"index":{"_id": 7}}
{"empId" : "777","name" : "员工7","age" : 60,"sex" : "女","mobile" : "19000007777","salary":52130,"deptName" : "测试部","provice" : "湖北省","city":"黄冈市","area":"边城区","address" : "湖北省黄冈市边城区","content" : "i like elasticsearch developer"}
{"index":{"_id": 8}}
{"empId" : "888","name" : "员工8","age" : 19,"sex" : "女","mobile" : "19000008888","salary":60000,"deptName" : "技术部","provice" : "湖北省","city":"武汉","area":"汉阳区","address" : "湖北省武汉市江汉大学","content" : "i like spark language"}
{"index":{"_id": 9}}
{"empId" : "999","name" : "员工9","age" : 40,"sex" : "男","mobile" : "19000009999","salary":23000,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市郑州大学","content" : "i like java developer"}
{"index":{"_id": 10}}
{"empId" : "101010","name" : "张湖北","age" : 35,"sex" : "男","mobile" : "19000001010","salary":18000,"deptName" : "测试部","provice" : "湖北省","city":"武汉","area":"高新开发区","address" : "湖北省武汉市东湖高新","content" : "i like java developer i also like  elasticsearch"}
{"index":{"_id": 11}}
{"empId" : "111111","name" : "王河南","age" : 61,"sex" : "男","mobile" : "19000001011","salary":10000,"deptName" : "销售部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am not like  java "}
{"index":{"_id": 12}}
{"empId" : "121212","name" : "张大学","age" : 26,"sex" : "女","mobile" : "19000001012","salary":1321,"deptName" : "测试部",,"provice" : "河南省","city":"开封市","area":"金明区","address" : "河南省开封市河南大学","content" : "i am java developer  thing java is good"}
{"index":{"_id": 13}}
{"empId" : "131313","name" : "李江汉","age" : 36,"sex" : "男","mobile" : "19000001013","salary":1125,"deptName" : "销售部","provice" : "河南省","city":"郑州市","area":"二七区","address" : "河南省郑州市二七区","content" : "i like java and java is very best i like it do you like java "}
{"index":{"_id": 14}}
{"empId" : "141414","name" : "王技术","age" : 45,"sex" : "女","mobile" : "19000001014","salary":6222,"deptName" : "测试部",,"provice" : "河南省","city":"郑州市","area":"金水区","address" : "河南省郑州市金水区","content" : "i like c++"}
{"index":{"_id": 15}}
{"empId" : "151515","name" : "张测试","age" : 18,"sex" : "男","mobile" : "19000001015","salary":20000,"deptName" : "技术部",,"provice" : "河南省","city":"郑州市","area":"高新开发区","address" : "河南省郑州高新开发区","content" : "i think spark is good"}

我们搜索插入的数据是否正确及 info字段是否存在?

image-20240317173939734

很显然是不存在这个字段的,但是我们搜索的时候却可以使用info字段取匹配

get /testcopy/_search
{
  "query":{
    "match_phrase": {
      "info": "员工"
    }
  }
}

image-20240317174049137

get /testcopy/_search
{
  "query":{
    "match_phrase": {
      "info": "湖北"
    }
  }
}

image-20240317174135488

至此 我们已经能够利用 CopyTo字段组合来实现逻辑多字段搜索,可以看到存储结构上并没有 info字段,但是我们可以用copy_to把多个字段关联起来实现多字段搜索.

loper thing java is good"}
{“index”:{“_id”: 13}}
{“empId” : “131313”,“name” : “李江汉”,“age” : 36,“sex” : “男”,“mobile” : “19000001013”,“salary”:1125,“deptName” : “销售部”,“provice” : “河南省”,“city”:“郑州市”,“area”:“二七区”,“address” : “河南省郑州市二七区”,“content” : “i like java and java is very best i like it do you like java “}
{“index”:{”_id”: 14}}
{“empId” : “141414”,“name” : “王技术”,“age” : 45,“sex” : “女”,“mobile” : “19000001014”,“salary”:6222,“deptName” : “测试部”,“provice” : “河南省”,“city”:“郑州市”,“area”:“金水区”,“address” : “河南省郑州市金水区”,“content” : “i like c++”}
{“index”:{“_id”: 15}}
{“empId” : “151515”,“name” : “张测试”,“age” : 18,“sex” : “男”,“mobile” : “19000001015”,“salary”:20000,“deptName” : “技术部”,“provice” : “河南省”,“city”:“郑州市”,“area”:“高新开发区”,“address” : “河南省郑州高新开发区”,“content” : “i think spark is good”}


我们搜索插入的数据是否正确及 info字段是否存在?

[外链图片转存中...(img-byM2NlK2-1710668677317)]

很显然是不存在这个字段的,但是我们搜索的时候却可以使用info字段取匹配

```json
get /testcopy/_search
{
  "query":{
    "match_phrase": {
      "info": "员工"
    }
  }
}

[外链图片转存中…(img-be8FlMn8-1710668677317)]

get /testcopy/_search
{
  "query":{
    "match_phrase": {
      "info": "湖北"
    }
  }
}

[外链图片转存中…(img-BMqw1ekq-1710668677318)]

至此 我们已经能够利用 CopyTo字段组合来实现逻辑多字段搜索,可以看到存储结构上并没有 info字段,但是我们可以用copy_to把多个字段关联起来实现多字段搜索.

🌟至此本篇就结束了,下一篇将介绍ES统计查询语法,希望和小伙伴们可以继续坚持学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/463991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[ Linux ] vim的使用(附:命令模式的常见命令列表)

1.下载安装 这里是在通过yum进行下载安装 yum install -y vim 2.了解 vim是一款编辑器&#xff0c;它具有多模式的特点 主要有&#xff1a;插入模式&#xff0c;命令模式&#xff0c;底行模式 3.使用 打开 vim 文件名 命令模式的常见命令列表 插入模式 按「 i 」切换…

建设IAM/IDM统一身份管理,实现系统之间的单点登录(SSO)

企业实施身份管理的现状&#xff1a; 1.身份存储分散&#xff0c;不能统一供应诸多应用系统&#xff0c;企业用户信息常常存在于多个系统&#xff0c;如HR系统有一套用户信息&#xff0c;OA系统也有一套用户信息&#xff0c;身份存储不集中&#xff0c;不能统一地为诸多应用系…

BUUCTF-WEB1

[ACTF2020 新生赛]Exec1 1.打开靶机 是一个ping命令 2.利用管道符“|” ping一下本地主机并查看ls ping 127.0.0.1 | ls 可以看到回显的内容是一个文件 127.0.0.1 | cat index.php #查看主机下index.php 127.0.0.1 | ls / #查看主机根目录下的文件 看的一个flag文件 …

C++:菱形继承与虚继承

看下面这个示例代码 class A{ public: int num10; A(){cout<<"A构造"<<endl;} virtual void fun(){cout<<"A虚函数"<<endl;} };class B:public A{ public: B(){cout<<"B构造"<<endl;} void fun(){cout<…

Linux基本使用

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;热门专栏&#xff1a;网络原理&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 Linux是什么&#xff1f; Linux常用命令介绍 命令提示…

云服务器容器常用操作系统介绍

常用操作系统介绍 开源软件国内镜像源Alpine操作系统介绍镜像源修改镜像源apk包管理器 Debian操作系统介绍镜像源修改镜像源apt包管理器 ubuntu操作系统介绍修改镜像源apt包管理器 CentOS操作系统介绍修改镜像源yum包管理器 开源软件国内镜像源 名称地址南京大学mirror.nju.ed…

【安全类书籍-2】Web渗透测试:使用Kali Linux

目录 内容简介 作用 下载地址 内容简介 书籍的主要内容是指导读者如何运用Kali Linux这一专业的渗透测试平台对Web应用程序进行全面的安全测试。作者们从攻击者的视角出发,详细阐述了渗透测试的基本概念和技术,以及如何配置Kali Linux以适应渗透测试需求。书中不仅教授读者…

初识Java篇(JavaSE基础语法)(1)

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a; 我要学编程(ಥ_ಥ)-CSDN博客 目录 前言&#xff1a; 初识Java 运行Java程序 注释 标识符 关键字 数据类型与变量 字面常量 数据类型 变量 类型转换 类型提升 字…

Android Kotlin(五)数据流StateFlow和LiveData

Android 上的 Kotlin 数据流 在协程中&#xff0c;与仅返回单个值的挂起函数相反&#xff0c;数据流可按顺序发出多个值。数据流以协程为基础构建&#xff0c;可提供多个值。从概念上来讲&#xff0c;数据流是可通过异步方式进行计算处理的一组数据序列。所发出值的类型必须…

【C语言】字符函数与字符串函数以及内存函数 { 超详细攻略,一篇学会 }

今日分享&#xff1a;字符、字符串函数和内存函数 内存函数就是对内存进行操作的函数 字符串函数就是对字符串进行操作的函数 字符函数就是对字符进行操作的函数 str前缀的函数是字符串函数&#xff0c;头文件string.h mem前缀的函数是内存函数&#xff0c;头文件stdlib.h 字符…

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据 使用环境: ubantu16 QT5.7 开发板GEC6818 实现要求&#xff1a; 利用A53按键1、按键2与温湿度传感器完成QT界面动态显示温湿度记录&#xff0c;并指定温湿度记录超过指定范围&#xff0c;进行报警&#xff08;LED&#…

21-分支和循环语句_while语句(中)(初阶)

21-2 代码准备 getchar()&#xff1a;获取字符 int ch getchar(); //把获取的字符的ASCII码值放在ch中 int main() {int ch getchar();printf("%c\n", ch); //ch存的是该字符的ASCII码值&#xff0c;此处以字符形式打印ASCII码值对应的字符putchar(ch); } 运…

MATLAB的多项式相加

多项式的加减在阶次相同的情况下可直接运算&#xff0c;若两个相加减的多项式阶次不同&#xff0c;则低阶多项式必须用零填补高阶项系数&#xff0c;使其与高阶多项式有相同的阶次。而且通常情况下&#xff0c;进行加减的两个多项 式的阶次不会相同&#xff0c;这时可以自定义一…

JVM从1%到99%【精选】-【初步认识】

目录 1.java虚拟机 2.JVM的位置 3.代码的执行流程 4.JVM的架构模型 5.JVM的生命周期 6.JVM的整体结构 1.java虚拟机 Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。JVM平台的各种语言可以共享Java…

数据同步操作需要注意哪些点?

前言 有时候基于业务&#xff0c;我们会做一些数据清洗&#xff0c;或者老项目数据同步新项目的相关操作。在做这些业务的时候&#xff0c;往往需要注意一些必要的关键点&#xff0c;否则会造成数据的错乱&#xff0c;我们知道数据一单错乱是很难处理的。 参考文章 原作者&a…

unittest--封装excel操作

封装excel操作 操作流程类和对象初始化对象操作获取表格的数据初始化一个用于操作Excel文件的对象获取表头和所有测试用例数据数据拼接 (dict)主函数调用 操作流程 1、初始化表格对象&#xff1a; 文件路径workbook&#xff0c;表单名称sheet_name 2、初始化sheet对象 &#xf…

RIPGeo参文31—36(关于对比学习):鼓励对同一数据点进行各种增强(视图),以学习更健壮的表示

RIPGeo中有: —干扰参数。在内部最大化中,我们提出了步骤,以增加损失的方向更新。我们的方法不是用简单的一步方案最大化内部部分,而是在每次迭代结束时将扰动投影到球面空间上(第2-7行),这允许模型产生更微妙但有价值的扰动[31]。 [31] A. Kurakin, I. J. Goodfellow…

ChatGPT丨“智领科研新纪元:AI大模型,您的第二大脑!“

AI大模型引领未来智慧科研暨ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的应用 以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数…

【蓝桥杯嵌入式】四、各种外设驱动(七)定时器的输出比较功能

温馨提示&#xff1a;本文不会重复之前提到的内容&#xff0c;如需查看&#xff0c;请参考附录 【蓝桥杯嵌入式】附录 重点提炼&#xff1a; 根据手册内容&#xff0c;输出比较模式&#xff08;output Compare CHx&#xff09;的功能主要需要由以下参数决定&#xff1a; 通…

Ubuntu Flask 运行 gunicorn+Nginx 部署

linux Ubuntu 下运行python 程序出现killed 原因&#xff1a;CPU或内存限制&#xff1a;在华为云上&#xff0c;你可能有CPU或内存使用的限制。例如&#xff0c;如果你使用的是一个固定大小的实例&#xff0c;那么超过该实例的CPU或内存限制可能会导致进程被杀死。 参考&am…
最新文章