`

理解“query then fetch”和“dfs query then fetch”

阅读更多

查询的代码:

$ curl -XGET localhost:9200/startswith/test/_search?pretty -d '{
        "query": {
        "match_phrase_prefix": {
           "title": {
             "query": "d",
             "max_expansions": 5
           }
         }
       }
     }' | grep title

      "_score" : 1.0, "_source" : {"title":"drunk"}
      "_score" : 0.30685282, "_source" : {"title":"dzone"}
      "_score" : 0.30685282, "_source" : {"title":"data"}
      "_score" : 0.30685282, "_source" : {"title":"drive"}

为何文档“drunk”分数为1.0,而其余的分数是0.3?难道这些文档不应该是相同的分数么,因为他们都同等地匹配了“d”。答案是肯定的,但是这个分数本身也有比较合理的地方。

相关性打分

ES使用的打分算法包含了称之为“TF-IDF”的统计信息来帮助计算处于那个索引中的文档的相关性。

TFIDF基本思想就是“一个项在文档中出现的次数越多,那么这个文档更加相关;但相关性会被这个项在整个文档库中的次数削弱”。

稀有项出现在相对少的文档中,那么任何查询匹配了一个稀有项的相关性就变得很高。相反,平常项到处都有,他们的相关性就低了。

当用户执行一个搜索时,ES面对一个有趣的困境。你的查询需要找到所有相关的文档,但是这些文档分布在你的cluster中的任何数目的shard中。

每个shard是一个Lucene的索引,保存了自身的TF和DF统计信息。一个shard只知道在其自身中出现的次数,而非整个cluster。

但是相关算法使用了TF-IDF,它需要知道对于整个索引的而不是对每个shard的TF和DF么?

默认搜索类型:query then fetch

答案:是也不是。默认情形下,ES会使用一个称之为Query then fetch的搜索类型。它运作的方式如下:

  1. 发送查询到每个shard
  2. 找到所有匹配的文档,并使用本地的Term/Document Frequency信息进行打分
  3. 对结果构建一个优先队列(排序,标页等)
  4. 返回关于结果的元数据到请求节点注意,实际文档还没有发送,只是分数
  5. 来自所有shard的分数合并起来,并在请求节点上进行排序,文档被按照查询要求进行选择
  6. 最终,实际文档从他们各自所在的独立的shard上检索出来
  7. 结果被返回给用户

这个系统一般是能够良好地运作的。大多数情形下,你的索引有足够的文档来平滑Term/Document frequency统计信息。因此,尽管每个shard不一定拥有完整的关于整个cluster的frequency信息,结果仍然足够好,因为fequency在每个地方基本上是类似的。

但是在我们开头提起的那个查询,默认搜索类型有时候会失败。

dfs query then fetch

在上篇文章中,我们默认建立了一个索引,ES通常使用5个shard。接着插入了5个文档进入索引,向ES发送请求返回相关结果和准确的分数。其结果并不是很公平,对吧?

这是由于默认的搜索类型导致的,每个shard仅仅包含一个或者两个文档(ES使用hash确保随机分布)。当我们要求ES计算分数时候,每个shard仅仅拥有关于五个文档的一个很窄的视角。所以分数是不准确的。

幸运的是,ES并没有让你无所适从。如果你遇到了这样的打分偏离的情形,ES提供了一个称为“DFS Query Then Fetch”。这个过程基本和Query Then Fetch类型,除了它执行了一个预查询来计算整体文档的frequency。

  1. 预查询每个shard,询问Term和Document frequency
  2. 发送查询到每隔shard
  3. 找到所有匹配的文档,并使用全局的Term/Document Frequency信息进行打分
  4. 对结果构建一个优先队列(排序,标页等)
  5. 返回关于结果的元数据到请求节点注意,实际文档还没有发送,只是分数
  6. 来自所有shard的分数合并起来,并在请求节点上进行排序,文档被按照查询要求进行选择
  7. 最终,实际文档从他们各自所在的独立的shard上检索出来
  8. 结果被返回给用户

如果我们使用这个新的搜索类型,那么获得的结果更加合理了(这些都一样的):

$ curl -XGET 'localhost:9200/startswith/test/_search?pretty=true&search_type=dfs_query_then_fetch' -d '{
        "query": {
        "match_phrase_prefix": {
           "title": {
             "query": "d",
             "max_expansions": 5
           }
         }
       }
     }' | grep title

      "_score" : 1.9162908, "_source" : {"title":"dzone"}
      "_score" : 1.9162908, "_source" : {"title":"data"}
      "_score" : 1.9162908, "_source" : {"title":"drunk"}
      "_score" : 1.9162908, "_source" : {"title":"drive"}

结论

当然,更好准确性不是免费的。预查询本身会有一个额外的在shard中的轮询,这个当然会有性能上的问题(跟索引的大小,shard的数量,查询的频率等)。在大多数情形下,是没有必要的,拥有足够的数据可以解决这样的问题。

但是有时候,你可能会遇到奇特的打分场景,在这些情况中,知道如何使用DFS query then fetch去进行搜索执行过程的微调还是有用的。

 

 

 

http://www.jianshu.com/p/c7529b98993e

分享到:
评论

相关推荐

    javascript实现fetch请求返回的统一拦截

    然而,fetch默认并不提供请求和响应的拦截器,这对于需要进行全局处理,比如鉴权、错误处理等场景并不方便。本篇文章主要探讨如何使用JavaScript实现fetch请求返回的统一拦截。 首先,我们需要理解拦截器的目的。...

    西门子 TCP通信中的Fetch和Write用法

    西门子PLC中的TCP通信主要包括FETCH和WRITE两种通信方式,这两种方式无需在PLC侧编程,只需要进行一些简单的配置即可实现与S5设备或PC的数据交换。 首先,我们需要使用带有FETCHWRITE功能的模块。在进行硬件组态后...

    JavaScript 用fetch 实现异步下载文件功能

    调用fetch后,通常会链式调用`.then()`方法来处理返回的Response对象,该对象包含了请求的完整响应信息。 在介绍的实例代码中,我们首先定义了一个按钮元素,当用户点击该按钮时,会触发文件的异步下载。具体步骤...

    Node.js-d3-fetch这个模块提供基于Fetch之上的便捷解析

    Fetch API以Promise为基础,支持异步操作,提供了更简洁、更易于理解和使用的接口。`d3-fetch`则是在这个基础上进一步优化,添加了对JSON、CSV、TSV等数据格式的便捷解析功能。 **d3-fetch的关键特性** 1. **简洁...

    JavaScript - Fetch实现短信验证码注册登录完整示例:JavaScript - Fetch.js和附件说明

    JavaScript中的Fetch API是一种现代的、基于Promise的网络请求方法,用于替代传统的XMLHttpRequest。...通过阅读和理解这些资源,你可以了解到如何在实际项目中运用Fetch API来实现短信验证码的注册和登录功能。

    vue fetch中的.then()的正确使用方法

    总的来说,Vue中正确使用 `fetch` 和 `.then()` 的关键在于理解每个 `.then()` 都应处理上一个Promise返回的结果,并确保正确地处理 `fetch` 响应,包括检查状态、解析数据等。同时,使用 `.catch()` 处理可能出现的...

    Node.js-node-fetch一个轻量级的模块将window.fetch带至node.js和io.js

    至于压缩包文件`bitinn-node-fetch-95286f5`,根据命名规则,这可能是`node-fetch`项目的某个特定版本(95286f5可能是Git仓库中的一个提交哈希),包含了源代码和其他相关文件。如果你需要深入了解`node-fetch`的...

    Hibernate Fetch 的作用

    在深入探讨Hibernate Fetch的...正确理解和运用Fetch策略,对于优化Hibernate应用程序的性能和响应速度具有重要意义。在实践中,应根据具体业务场景和性能需求,权衡使用Fetch策略的利弊,以达到最佳的系统性能表现。

    Oracle 中使用 fetch bulk collect into 批量效率的读取游标数据

    Oracle 中使用 fetch bulk collect into 批量效率的读取游标数据 Oracle 中的游标数据读取是数据库开发中非常常见的操作。通常,我们使用 fetch some_cursor into var1, var2 形式来获取游标数据,当游标中的记录数...

    OracleFetch

    最后,Autonomy提供了详细的配置文件示例,帮助用户更好地理解和应用OracleFetch。这些示例涵盖了常见的应用场景,从简单的数据导入到复杂的多表关联查询,为用户提供了一套完整的解决方案。 总之,OracleFetch作为...

    MongoDB查询指定域语言Rogue.zip

    val query = Venue where (_.venuename eqs "Starbucks")query.count()query.countDistinct(_.mayor)query.fetch()query.fetch(n)query.get() // equivalent to query.fetch(1).headOptionquery.foreach{v: Venue =>...

    Fetch+Promise教程

    Fetch API 的概念和用法、Headers 对象、Request 对象等都是学习 ES6 和前端数据交互的必备知识。 Fetch API 概念和用法 Fetch API 提供了对 Request 和 Response 对象的通用定义,可以被使用到很多场景中,例如 ...

    一个微小的ES6fetch包装不需要对API大动干戈

    首先,`fetch` API的基本用法是接收一个URL和一个可选的配置对象。例如,获取JSON数据通常需要设置`'Content-Type'`为`'application/json'`,并处理响应的`json()`方法。一个简单的`fetch`调用可能如下: ```...

    QT操作SQLite数据库示例

    QT操作SQLite数据库是一个常见的任务,尤其在开发C++应用程序时,...在提供的SQLiteEx压缩包文件中,可能包含了更详细的示例代码,包括但不限于上述操作,你可以进一步研究和学习,以便更好地理解和应用这些概念。

    JavaScript - Fetch.js、JavaScript - jQuery、JavaScript - XHR.js.zip

    Fetch API是现代JavaScript中用于异步数据获取的新标准,它提供了一种更简洁、更易于理解和使用的方式来替代传统的XMLHttpRequest。在`JavaScript - Fetch.js`中,你可能会看到以下核心代码: ```javascript ...

    浅谈Fetch 数据交互方式

    《深入理解Fetch数据交互方式》 Fetch API是现代Web开发中用于进行数据交互的重要工具,它的出现是为了替代传统的XMLHttpRequest(XHR)。Fetch以其简洁、优雅的Promise语法,使得异步数据请求变得更加直观和易于...

    flutter_background_fetch,ios和android的后台定期回调。包括Android无头机制.zip

    Flutter Background Fetch 是一个开源项目,由晶体管软件(Transistor Software)开发,专门用于实现iOS和Android设备上的后台定期回调功能。这个库旨在解决移动应用在后台时执行任务的需求,例如更新数据、发送推送...

    Laravel开发-fetch

    6. **分页(Pagination)**:如果数据量大,`fetch`可能涉及到分页,Laravel提供了`paginate()`和`simplePaginate()`方法。 7. **Scope**:Laravel允许定义模型的全局和局部范围,`fetch`可能在某个范围内执行查询...

    fetch-california-housing()数据集

    总结,`fetch_california_housing()`数据集是机器学习初学者和专业人士的重要资源,它提供了一个真实的、有一定挑战性的回归问题,可以帮助我们理解和实践各种回归算法。通过深入研究这个数据集,可以提升对机器学习...

Global site tag (gtag.js) - Google Analytics