[Elasticsearch] 全文搜索 (一) 基础概念和match查询
全文搜索(Full Text Search)
现在我们已经讨论了搜索结构化数据的一些简单用例,是时候开始探索全文搜索了 - 如何在全文字段中搜索来找到最相关的文档。
对于全文搜索而言,最重要的两个方面是:
相关度(Relevance)
查询的结果按照它们对查询本身的相关度进行排序的能力,相关度可以通过TF/IDF,参见什么是相关度,地理位置的邻近程度(Proximity to a Geo-location),模糊相似性(Fuzzy Similarity)或者其它算法进行计算。
解析(Analysis)
解析用来将一块文本转换成单独的,规范化的词条(Tokens),参见解析和解析器(Analysis and Analyzers),用来完成:(a)倒排索引(Inverted Index)的创建;(b)倒排索引的查询。
一旦我们开始讨论相关度或者解析,也就意味着我们踏入了查询(Query)的领域,而不再是过滤器(Filter)。
基于词条(Term-based)和全文(Full-text)
尽管所有的查询都会执行某种程度的相关度计算,并不是所有的查询都存在解析阶段。除了诸如bool
或者function_score
这类完全不对文本进行操作的特殊查询外,对于文本的查询可以被划分两个种类:
基于词条的查询(Term-based Queries)
类似term
和fuzzy
的查询是不含有解析阶段的低级查询(Low-level Queries)。它们在单一词条上进行操作。一个针对词条Foo
的term
查询会在倒排索引中寻找该词条的精确匹配(Exact term),然后对每一份含有该词条的文档通过TF/IDF进行相关度_score
的计算。
尤其需要记住的是term
查询只会在倒排索引中寻找该词条的精确匹配 - 它不会匹配诸如foo
或者FOO
这样的变体。它不在意词条是如何被保存到索引中。如果你索引了["Foo", "Bar"]
到一个not_analyzed
字段中,或者将Foo Bar
索引到一个使用whitespace
解析器的解析字段(Analyzed Field)中,它们都会在倒排索引中得到两个词条:"Foo"
以及"Bar"
。
全文查询(Full-text Queries)
类似match
或者query_string
这样的查询是高级查询(High-level Queries),它们能够理解一个字段的映射:
- 如果你使用它们去查询一个
date
或者integer
字段,它们会将查询字符串分别当做日期或者整型数。 - 如果你查询一个精确值(
not_analyzed
)字符串字段,它们会将整个查询字符串当做一个单独的词条。 - 但是如果你查询了一个全文字段(
analyzed
),它们会首先将查询字符串传入到合适的解析器,用来得到需要查询的词条列表。
一旦查询得到了一个词条列表,它就会使用列表中的每个词条来执行合适的低级查询,然后将得到的结果进行合并,最终产生每份文档的相关度分值。
我们会在后续章节中详细讨论这个过程。
在很少的情况下,你才需要直接使用基于词条的查询(Term-based Queries)。通常你需要查询的是全文,而不是独立的词条,而这个工作通过高级的全文查询来完成会更加容易(在内部它们最终还是使用的基于词条的低级查询)。
如果你发现你确实需要在一个not_analyzed
字段上查询一个精确值,那么考虑一下你是否真的需要使用查询,而不是使用过滤器。
单词条查询通常都代表了一个二元的yes|no
问题,这类问题通常使用过滤器进行表达更合适,因此它们也能够得益于过滤器缓存(Filter Caching):
GET /_search
{
"query": {
"filtered": {
"filter": {
"term": { "gender": "female" }
}
}
}
}
match
查询
在你需要对任何字段进行查询时,match
查询应该是你的首选。它是一个高级全文查询,意味着它知道如何处理全文字段(Full-text, analyzed
)和精确值字段(Exact-value,not_analyzed
)。
即便如此,match
查询的主要使用场景仍然是全文搜索。让我们通过一个简单的例子来看看全文搜索时如何工作的。
索引一些数据
首先,我们会创建一个新的索引并通过bulk
API索引一些文档:
DELETE /my_index PUT /my_index
{ "settings": { "number_of_shards": 1 }} POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "title": "The quick brown fox" }
{ "index": { "_id": 2 }}
{ "title": "The quick brown fox jumps over the lazy dog" }
{ "index": { "_id": 3 }}
{ "title": "The quick brown fox jumps over the quick dog" }
{ "index": { "_id": 4 }}
{ "title": "Brown fox brown dog" }
注意到以上在创建索引时,我们设置了number_of_shards
为1:在稍后的相关度坏掉了(Relevance is broken)一节中,我们会解释为何这里创建了一个只有一个主分片(Primary shard)的索引。
单词查询(Single word query)
第一个例子我们会解释在使用match
查询在一个全文字段中搜索一个单词时,会发生什么:
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": "QUICK!"
}
}
}
ES会按照如下的方式执行上面的match
查询:
检查字段类型
title
字段是一个全文字符串字段(analyzed
),意味着查询字符串也需要被分析。解析查询字符串
查询字符串
"QUICK!"
会被传入到标准解析器中,得到的结果是单一词条"quick"
。因为我们得到的只有一个词条,match
查询会使用一个term
低级查询来执行查询。找到匹配的文档
term
查询会在倒排索引中查询"quick"
,然后获取到含有该词条的文档列表,在这个例子中,文档1
,2
,3
会被返回。对每份文档打分
term
查询会为每份匹配的文档计算其相关度分值_score
,该分值通过综合考虑词条频度(Term Frequency)("quick"
在匹配的每份文档的title
字段中出现的频繁程度),倒排频度(Inverted Document Frequency)("quick"
在整个索引中的所有文档的title
字段中的出现程度),以及每个字段的长度(较短的字段会被认为相关度更高)来得到。参考什么是相关度(What is Relevance?)
这个过程会给我们下面的结果(有省略):
"hits": [
{
"_id": "1",
"_score": 0.5,
"_source": {
"title": "The quick brown fox"
}
},
{
"_id": "3",
"_score": 0.44194174,
"_source": {
"title": "The quick brown fox jumps over the quick dog"
}
},
{
"_id": "2",
"_score": 0.3125,
"_source": {
"title": "The quick brown fox jumps over the lazy dog"
}
}
]
文档1最相关,因为它的title
字段短,意味着quick
在它所表达的内容中占比较大。 文档3比文档2的相关度更高,因为quick
出现了两次。
REFERENCE FROM : http://blog.csdn.net/dm_vincent/article/details/41693125
[Elasticsearch] 全文搜索 (一) 基础概念和match查询的更多相关文章
- Elasticsearch全文搜索——adout
现在尝试下稍微高级点儿的全文搜索——一项传统数据库确实很难搞定的任务. 搜索下所有喜欢攀岩(rock climbing)的雇员: curl -XGET 'localhost:9200/megacorp ...
- Elasticsearch 全文搜索
1,匹配查询(match) match查询主要的应用场景是进行全文搜索: // 1,初始化数据 DELETE /my_index PUT /my_index { "settings" ...
- 【Elasticsearch学习】之基础概念
Elasticsearch是一个近实时的分布式搜索引起,其底层基于开源全文搜索库Lucene:Elasticsearch对Lucene进行分装,对外提供REST API 的操作接口.基于 ES,可以快 ...
- elasticsearch全文搜索
1.创建索引 PUT 192.168.100.102:9200/news 2.创建mapping POST 192.168.100.102:9200/news/new/_mapping { " ...
- Elasticsearch 全文搜索和keyword search字段的mapping定义
在ES5.0之前我们对于需要keyword search的字段都是这样定义的: { "field name":{ "type": "string&qu ...
- Elasticsearch系列---搜索执行过程及scroll游标查询
概要 本篇主要介绍一下分布式环境中搜索的两阶段执行过程. 两阶段搜索过程 回顾我们之前的CRUD操作,因为只对单个文档进行处理,文档的唯一性很容易确定,并且很容易知道是此文档在哪个node,哪个sha ...
- ElasticSearch全文搜索引擎(A)
文章:[Elasticsearch] 全文搜索 (一) - 基础概念和match查询 全文检索,是从最初的字符串匹配和简单的布尔逻辑检索技术,演进到能对超大文本.语音.图像.活动影像等非结构化数据进行 ...
- 〈四〉ElasticSearch的认识:基础原理的补充
目录 想想我们漏了什么 回顾 补回 集群的建立 集群发现机制 配置文件 健康状态 补充: 小节总结 分片的管理 梳理 分片的均衡分配 主副分片的排斥 容错性: 数据路由 对于集群健康状态的影响 小节总 ...
- SQL Server 全文搜索
SQL Server 的全文搜索(Full-Text Search)是基于分词的文本检索功能,依赖于全文索引.全文索引不同于传统的平衡树(B-Tree)索引和列存储索引,它是由数据表构成的,称作倒转索 ...
随机推荐
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】
一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...
- poj1273 Drainage Ditches
Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 68414 Accepted: 2648 ...
- FragmentTransaction.replace() 你不知道的坑
一.起源: 先看效果,在linearLayout中添加了4个Fragment,然后点击替换一次确替换了两个Fragment,引发了我的研究兴趣: 第一次启动 ...
- 多线程进行http请求
昨天需要一个线下脚本进行单播推送,大约有1kw个用户,考虑到推送速度就临时搞了个请求线上的一个脚本 /** * 临时支持invoke单播推送 */ #include <stdio.h> # ...
- JSTL中的TLD配置和使用。
一,JSTL介绍: JSTL标签库,是日常开发经常使用的,也是众多标签中性能最好的.把常用的内容,放在这里备份一份,随用随查.尽量做到不用查,就可以随手就可以写出来.这算是Java程序员的基本功吧,一 ...
- codevs 2606 约数和问题
题目描述 Description Smart最近沉迷于对约数的研究中. 对于一个数X,函数f(X)表示X所有约数的和.例如:f(6)=1+2+3+6=12.对于一个X,Smart可以很快的算出f(X) ...
- Windows 8.1 新增控件之 DatePicker
大年初一来介绍一个简单易用的DatePicker 控件,这个控件是新增的?印象里很早就有了啊,Anyway来看看Windows 8.1 里的DataPicker 有什么功能吧. 先来看看这个代码,很简 ...
- 【转】$_POST 与 php://input的区别分析
$data = file_get_contents("php://input"); php://input 是个可以访问请求的原始数据的只读流. POST 请求的情况下,最好使用 ...
- Java 8 Lambda表达式探险
为什么? 我们为什么需要Lambda表达式 主要有三个原因: > 更加紧凑的代码 比如Java中现有的匿名内部类以及监听器(listeners)和事件处理器(hand ...
- caffe的python接口学习(1):生成配置文件
caffe是C++语言写的,可能很多人不太熟悉,因此想用更简单的脚本语言来实现.caffe提供matlab接口和python接口,这两种语言就非常简单,而且非常容易进行可视化,使得学习更加快速,理解更 ...