原文链接:http://blog.csdn.net/dm_vincent/article/details/41863015
以字段为中心的查询(Field-centric Queries)
上述提到的三个问题都来源于most_fields是以字段为中心(Field-centric),而不是以词条为中心(Term-centric):它会查询最多匹配的字段(Most matching fields),而我们真正感兴趣的最匹配的词条(Most matching terms)。
NOTE
best_fields同样是以字段为中心的,因此它也存在相似的问题。
首先我们来看看为什么存在这些问题,以及如何解决它们。
问题1:在多个字段中匹配相同的单词
考虑一下most_fields查询是如何执行的:ES会为每个字段生成一个match查询,让后将它们包含在一个bool查询中。
我们可以将查询传入到validate-query API中进行查看:
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "Poland Street W1V",
"type": "most_fields",
"fields": [ "street", "city", "country", "postcode" ]
}
}
}
它会产生下面的解释(explaination):
(street:poland street:street street:w1v) (city:poland city:street city:w1v) (country:poland country:street country:w1v) (postcode:poland postcode:street postcode:w1v)
你可以发现能够在两个字段中匹配poland的文档会比在一个字段中匹配了poland和street的文档的分值要高。
问题2:减少长尾
在精度控制(Controlling Precision)一节中,我们讨论了如何使用and操作符和minimum_should_match参数来减少相关度低的文档数量:
{
"query": {
"multi_match": {
"query": "Poland Street W1V",
"type": "most_fields",
"operator": "and",
"fields": [ "street", "city", "country", "postcode" ]
}
}
}
但是,使用best_fields或者most_fields,这些参数会被传递到生成的match查询中。该查询的解释如下(译注:通过validate-query API):
(+street:poland +street:street +street:w1v) (+city:poland +city:street +city:w1v) (+country:poland +country:street +country:w1v) (+postcode:poland +postcode:street +postcode:w1v)
换言之,使用and操作符时,所有的单词都需要出现在相同的字段中,这显然是错的!这样做可能不会有任何匹配的文档。
问题3:词条频度
在什么是相关度(What is Relevance)一节中,我们解释了默认用来计算每个词条的相关度分值的相似度算法TF/IDF:
词条频度(Term Frequency)
在一份文档中,一个词条在一个字段中出现的越频繁,文档的相关度就越高。
倒排文档频度(Inverse Document Frequency)
一个词条在索引的所有文档的字段中出现的越频繁,词条的相关度就越低。
当通过多字段进行搜索时,TF/IDF会产生一些令人惊讶的结果。
考虑使用first_name和last_name字段搜索"Peter Smith"的例子。Peter是一个常见的名字,Smith是一个常见的姓氏 - 它们的IDF都较低。但是如果在索引中有另外一个名为Smith Williams的人呢?Smith作为名字是非常罕见的,因此它的IDF值会很高!
像下面这样的一个简单查询会将Smith Williams放在Peter Smith前面(译注:含有Smith Williams的文档分值比含有Peter Smith的文档分值高),尽管Peter Smith明显是更好的匹配:
{
"query": {
"multi_match": {
"query": "Peter Smith",
"type": "most_fields",
"fields": [ "*_name" ]
}
}
}
smith在first_name字段中的高IDF值会压倒peter在first_name字段和smith在last_name字段中的两个低IDF值。
解决方案
这个问题仅在我们处理多字段时存在。如果我们将所有这些字段合并到一个字段中,该问题就不复存在了。我们可以向person文档中添加一个full_name字段来实现:
{
"first_name": "Peter",
"last_name": "Smith",
"full_name": "Peter Smith"
}
当我们只查询full_name字段时:
- 拥有更多匹配单词的文档会胜过那些重复出现一个单词的文档。
- minimum_should_match和operator参数能够正常工作。
- first_name和last_name的倒排文档频度会被合并,因此smith无论是first_name还是last_name都不再重要。
尽管这种方法能工作,可是我们并不想存储冗余数据。因此,ES为我们提供了两个解决方案 - 一个在索引期间,一个在搜索期间。
自定义_all字段
在元数据:_all字段中,我们解释了特殊的_all字段会将其它所有字段中的值作为一个大字符串进行索引。尽管将所有字段的值作为一个字段进行索引并不是非常灵活。如果有一个自定义的_all字段用来索引人名,另外一个自定义的_all字段用来索引地址就更好了。
ES通过字段映射中的copy_to参数向我们提供了这一功能:
PUT /my_index
{
"mappings": {
"person": {
"properties": {
"first_name": {
"type": "string",
"copy_to": "full_name"
},
"last_name": {
"type": "string",
"copy_to": "full_name"
},
"full_name": {
"type": "string"
}
}
}
}
}
现在first_name和last_name字段中的值会被拷贝到full_name字段中。
有了这个映射,我们可以通过first_name字段查询名字,last_name字段查询姓氏,或者full_name字段查询姓氏和名字。
NOTE
first_name和last_name字段的映射和full_name字段的索引方式的无关。full_name字段会从其它两个字段中拷贝字符串的值,然后仅根据full_name字段自身的映射进行索引。
跨域查询(Cross-fields Queries)
如果你在索引文档前就能够自定义_all字段的话,那么使用_all字段就是一个不错的方法。但是,ES同时也提供了一个搜索期间的解决方案:使用类型为cross_fields的multi_match查询。cross_fields类型采用了一种以词条为中心(Term-centric)的方法,这种方法和best_fields及most_fields采用的以字段为中心(Field-centric)的方法有很大的区别。它将所有的字段视为一个大的字段,然后在任一字段中搜索每个词条。
为了阐述以字段为中心和以词条为中心的查询的区别,看看以字段为中心的most_fields查询的解释(译注:通过validate-query API得到):
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "most_fields",
"operator": "and",
"fields": [ "first_name", "last_name" ]
}
}
}
operator设为了and,表示所有的词条都需要出现。
对于一份匹配的文档,peter和smith两个词条都需要出现在相同的字段中,要么是first_name字段,要么是last_name字段:
(+first_name:peter +first_name:smith) (+last_name:peter +last_name:smith)
而以词条为中心的方法则使用了下面这种逻辑:
(+first_name:peter +first_name:smith) (+last_name:peter +last_name:smith)
换言之,词条peter必须出现在任一字段中,同时词条smith也必须出现在任一字段中。
cross_fields类型首先会解析查询字符串来得到一个词条列表,然后在任一字段中搜索每个词条。仅这个区别就能够解决在以字段为中心的查询中提到的3个问题中的2个,只剩下倒排文档频度的不同这一问题。
幸运的是,cross_fields类型也解决了这个问题,从下面的validate-query请求中可以看到:
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "cross_fields",
"operator": "and",
"fields": [ "first_name", "last_name" ]
}
}
}
它通过混合(Blending)字段的倒排文档频度来解决词条频度的问题:
+blended("peter", fields: [first_name, last_name]) +blended("smith", fields: [first_name, last_name])
换言之,它会查找词条smith在first_name和last_name字段中的IDF值,然后使用两者中较小的作为两个字段最终的IDF值。因为smith是一个常见的姓氏,意味着它也会被当做一个常见的名字。
NOTE
为了让cross_fields查询类型能以最佳的方式工作,所有的字段都需要使用相同的解析器。使用了相同的解析器的字段会被组合在一起形成混合字段(Blended Fields)。
如果你包含了使用不同解析链(Analysis Chain)的字段,它们会以和best_fields相同的方被添加到查询中。比如,如果我们将title字段添加到之前的查询中(假设它使用了一个不同的解析器),得到的解释如下所示:
(+title:peter +title:smith) ( +blended("peter", fields: [first_name, last_name]) +blended("smith", fields: [first_name, last_name]) )
当使用了minimum_should_match以及operator参数时,这一点尤为重要。
逐字段提升(Per-field Boosting)
使用cross_fields查询相比使用自定义_all字段的一个优点是你能够在查询期间对个别字段进行提升。
对于first_name和last_name这类拥有近似值的字段,也许提升是不必要的,但是如果你通过title和description字段来搜索书籍,那么你或许会给予title字段更多的权重。这可以通过前面介绍的caret(^)语法来完成:
GET /books/_search
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "cross_fields",
"fields": [ "title^2", "description" ]
}
}
}
能够对个别字段进行提升带来的优势应该和对多个字段执行查询伴随的代价进行权衡,因为如果使用自定义的_all字段,那么只需要要对一个字段进行查询。选择能够给你带来最大收益的方案。
精确值字段(Exact-value Fields)
在结束对于多字段查询的讨论之前的最后一个话题是作为not_analyzed类型的精确值字段。在multi_match查询中将not_analyzed字段混合到analyzed字段中是没有益处的。
原因可以通过validate-query进行简单地验证,假设我们将title字段设置为not_analyzed:
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "cross_fields",
"fields": [ "title", "first_name", "last_name" ]
}
}
}
因为title字段时没有被解析的,它会以将整个查询字符串作为一个词条进行搜索!
title:peter smith ( blended("peter", fields: [first_name, last_name]) blended("smith", fields: [first_name, last_name]) )
很显然该词条在title字段的倒排索引中并不存在,因此永远不可能被找到。在multi_match查询中避免使用not_analyzed字段。
相关推荐
总的来说,Elasticsearch 7.17.8为Windows x86-64用户提供了一个高性能、可扩展的搜索和分析引擎,适用于日志分析、实时监控、数据挖掘等多个场景。通过深入理解其核心特性、配置选项以及与周边工具的协同工作,我们...
Elasticsearch Head 是一款功能强大的Elasticsearch管理工具,它以网页的形式提供友好的界面,便于用户对Elasticsearch集群进行监控、管理和操作。"es-head-0.1.4_0.crx.zip" 是这个插件的压缩包文件,版本为0.1.4,...
标题 "谷歌扩展字段脱敏 vite-react-cr3" 暗示了这个项目是关于构建一个谷歌浏览器扩展,其中涉及到了Vite、React以及可能的Chrome Extensions API的使用。描述中的内容简洁,没有提供额外信息,但我们可以根据标签...
ElasticSearch,简称为ES,是一个开源的、高度可扩展的分布式全文检索引擎。它基于 Java 开发,并利用 Lucene 作为其核心,实现了高效索引和搜索功能。ElasticSearch 通过Resultful API简化了与Lucene的交互,隐藏了...
6. 配置Elasticsearch:为了让Elasticsearch与`elasticsearch-head`通信,需要在Elasticsearch的配置文件`elasticsearch.yml`中添加允许跨域请求的设置,如`http.cors.enabled: true`和`http.cors.allow-origin: "*...
Elasticsearch-Head 是一款专为谷歌浏览器(Google Chrome)设计的插件,其主要功能是提供一个直观的用户界面,用于与Elasticsearch集群进行交互和测试数据接口。这款插件极大地简化了开发者和管理员对Elasticsearch...
**Elasticsearch-Head Chrome 插件详解** 在大数据时代,Elasticsearch作为一个高效、可扩展的全文搜索引擎,被广泛应用于日志分析、实时监控、数据挖掘等领域。为了方便用户管理和操作Elasticsearch集群,出现了...
- 在`elasticSearch.yml`配置文件中添加以下设置以启用跨域支持: ```yaml http.cors.enabled: true http.cors.allow-origin: "*" ``` - 保存文件后重启Elasticsearch服务。 5. **使用可视化工具查询索引**:...
**Elasticsearch-Head 插件详解** Elasticsearch 是一款功能强大的开源搜索引擎,它提供了分布式、全文检索、分析和存储数据的能力。而 Elasticsearch-Head 是一个基于浏览器的可视化插件,它允许用户通过Web界面...
Elasticsearch-Head360 是一个专为 Elasticsearch 设计的浏览器扩展,它提供了一个直观的图形用户界面(GUI),使得用户能够轻松地与 Elasticsearch 集群进行交互。这款插件尤其适合开发者、管理员以及对 Elastic...
Elasticsearch-Head 是一个非常实用的开源工具,主要用于可视化管理Elasticsearch集群。这个"elasticsearch-head-master.zip"文件包含的就是Elasticsearch-Head的最新稳定版本,它作为一个插件,可以提供对Elastic...
### Elasticsearch数据库的下载、配置及使用案例 #### 一、下载Elasticsearch 1. **访问官网**: 首先,访问Elasticsearch的官方网站(<https://www.elastic.co/downloads/elasticsearch>),该网站提供了不同版本...
Elasticsearch支持丰富的查询语法,包括匹配查询、范围查询、多字段查询、布尔查询等,使得数据检索变得灵活且强大。 在集群管理方面,Elasticsearch设计为分布式的,多个节点可以组成一个集群,通过选举产生主节点...
### Elasticsearch 数据库下载、配置、使用案例及项目源码详解 #### 一、Elasticsearch 数据库下载 Elasticsearch 是一款广泛使用的分布式搜索引擎和分析引擎,它基于 Lucene 构建并支持实时分析。Elasticsearch ...
这种方式可以方便地将Elasticsearch集成到现有的基于SQL的应用程序中,同时利用Elasticsearch的强大搜索和分析能力。 #### 破解背景及目的 X-Pack中的许多高级特性,例如安全认证、审计日志、机器学习等,都是在...
- 网络配置:需要设置网络主机地址,并允许跨域请求,这对于前后端分离或远程访问Elasticsearch服务尤为关键。 - CORS配置:设置允许的跨域请求源,以确保浏览器端的Kibana可以与Elasticsearch正常通信。 2. ...
标题 "解决方案 ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’" 提到的是一个在Web开发中常见的跨域问题。`Access-Control-Allow-Origin` 是一个用于控制资源跨域访问的...
- 同源策略:限制跨域请求的原因及解决方案(CORS、JSONP、IFrame)。 6. 性能优化: - 代码优化:避免阻塞渲染、减少重排和重绘、利用异步加载。 - 性能监控:使用Chrome DevTools的Performance面板进行性能...
消ES需在页面中配置及跨域问题,ES默认配置集群名改为原elasticsearch 修复后台统计热卖商品SQL错误,xmall-front-web模块支持SpringMVC文件上传配置 修改金额字段类型优化SQL与备注 优化后台页面 修复用户修改BUG ...
- 指浏览器根据用户输入的内容,自动填充表单字段的功能。 5. 浏览器内多个标签页之间的通信: - 可以通过localStorage、sessionStorage进行简单的数据共享和通信。 - 使用Broadcast Channel API进行更复杂的...