Elasticsearch(八)【NEST高级客户端--分析器】
分析是将文本(如任何电子邮件的正文)转换为添加到反向索引中进行搜索的tokens
或terms
的过程。 分析由analyzer
执行,分析器可以是内置分析器或每个索引定义的定制分析器。
书写分析器
测试分析器
书写分析器
有时候,您可以通过配置Elasticsearch内置分析器的工作原理,或将分析组件结合在一起来构建定制分析器,以定制方式分析文本。
分析链
分析器由三个组件构成:
0个或更多字符过滤器
正好是1个tokenizer分词
0或更多Token过滤器
在字段映射上指定分析器
当在类型上创建新字段时,通常在索引创建时创建类型映射时,还可以在使用Put Mapping API添加新字段时,在text
数据类型字段映射上指定分析器。
重要
虽然您可以向索引添加新类型,或向类型添加新字段,但是您不能添加新的分析器或对现有字段进行更改。 如果您这样做,已经编入索引的数据将不正确,您的搜索将无法正常工作。
当您需要更改现有的字段时,应该使用Reindex API重新建立数据
以下是一个简单的示例,指定Elasticsearch中的name
字段映射到项目类型上的Name
POCO属性,在索引时使用whitespace
var createIndexResponse = client.CreateIndex("my-index", c => c
.Mappings(m => m
.Map<Project>(mm => mm
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Analyzer("whitespace")
)
)
)
)
);
配置内置分析器
可以配置几个内置的分析器来改变其行为。 例如,standard
分析器可以配置为支持具有包含停止词令牌过滤器的停止词列表。
配置内置分析器需要基于内置分析器创建一个分析器
var createIndexResponse = client.CreateIndex("my-index", c => c
.Settings(s => s
.Analysis(a => a
.Analyzers(aa => aa
.Standard("standard_english", sa => sa
.StopWords("_english_")
)
)
)
)
.Mappings(m => m
.Map<Project>(mm => mm
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Analyzer("standard_english")
)
)
)
)
);
Elasticsearch中的英文词汇预定义列表
使用配置的standard_english
分析器
{
"settings": {
"analysis": {
"analyzer": {
"standard_english": {
"type": "standard",
"stopwords": [
"_english_"
]
}
}
}
},
"mappings": {
"project": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard_english"
}
}
}
}
}
创建自定义分析器
当内置分析仪不符合您的需求时,可以组合定制分析器。 自定义分析器是从您在分析链中看到的组件和位置增量间隙构建的,该位置增量间距决定了Elasticsearch 应该在数组元素之间插入的间距大小,当字段可以保存多个值时,例如List<string>
POCO属性。
对于这个例子,假设我们正索引编程问题的,问题内容是HTML和源代码
public class Question
{
public int Id { get; set; }
public DateTimeOffset CreationDate { get; set; }
public int Score { get; set; }
public string Body { get; set; }
}
基于我们对编程语言的领域知识,我们希望能够搜索包含“C#”的问题,但是使用standard
分析器“C#”将被分析并产生分词“c”。 这对于我们的用例来说是不行的,因为没有办法将有关“C#”的问题与另一种流行的编程语言“C”的问题区分开来。
我们可以使用自定义分析器解决我们的问题
var createIndexResponse = client.CreateIndex("questions", c => c
.Settings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("programming_language", mca => mca
.Mappings(new []
{
"c# => csharp",
"C# => Csharp"
})
)
)
.Analyzers(an => an
.Custom("question", ca => ca
.CharFilters("html_strip", "programming_language")
.Tokenizer("standard")
.Filters("standard", "lowercase", "stop")
)
)
)
)
.Mappings(m => m
.Map<Question>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Body)
.Analyzer("question")
)
)
)
)
);
我们的自定义question
分析器将对问题体进行以下分析
剥离HTML标签
将`C#`和`c#`分别映射到`"CSharp"`和`"csharp"`(所以#不会被tokenizer剥离)
tokenize使用标准的分词器
使用标准分词过滤器过滤分词
小写分词
删除停止分词
全文查询还将在搜索时间对问题主体的查询输入应用相同的分析,这意味着当有人搜索包含输入"C#"
时,它也将被分析并产生分词“csharp”,匹配问题体包含"C#"
(以及“csharp”和case不变量),因为应用的搜索时间分析与索引时间分析相同。
索引和搜索时间分析
使用前面的例子,我们可能不想将相同的分析应用于针对问题体的全文查询的查询输入;我们知道查询输入不会包含HTML标签,因此我们希望在搜索时间应用不同的分析。
除了要在查询时使用的分析器之外,还可以在创建搜索时使用的字段映射时指定分析器
var createIndexResponse = client.CreateIndex("questions", c => c
.Settings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("programming_language", mca => mca
.Mappings(new[]
{
"c# => csharp",
"C# => Csharp"
})
)
)
.Analyzers(an => an
.Custom("index_question", ca => ca
.CharFilters("html_strip", "programming_language")
.Tokenizer("standard")
.Filters("standard", "lowercase", "stop")
)
.Custom("search_question", ca => ca
.CharFilters("programming_language")
.Tokenizer("standard")
.Filters("standard", "lowercase", "stop")
)
)
)
)
.Mappings(m => m
.Map<Question>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Body)
.Analyzer("index_question")
.SearchAnalyzer("search_question")
)
)
)
)
);
这样就可以在索引时用index_question
分析器分析一个问题体的文本,并且使用不带html_strip
字符过滤器的search_question
分析器来分析问题体字段上的全文查询的输入。
也可以为每个查询指定搜索分析器,即对于来自映射中指定的请求的特定请求使用不同的分析器。 这可以在迭代和改进搜索策略时有用。
测试分析器
在建立自己的分析器时,测试分析器可以达到预期的效果
测试内置分析器
要开始使用Analyze API,我们可以测试一下内置分析器如何分析一段文本
var analyzeResponse = client.Analyze(a => a
.Analyzer("standard")
.Text("F# is THE SUPERIOR language :)")
);
这将从Elasticsearch返回以下响应
{
"tokens": [
{
"token": "f",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "is",
"start_offset": 3,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "the",
"start_offset": 6,
"end_offset": 9,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
这被反序列化为NEST的IAnalyzeResponse
的一个实例,我们可以使用它
foreach (var analyzeToken in analyzeResponse.Tokens)
{
Console.WriteLine($"{analyzeToken.Token}");
}
在我们的文本测试standard
分析器时,我们注意到了
F#被分词为"f"
停止分词"is"和"the"包括在内
"superior"包括在内,但我们也希望将"great"作为superior的同义词
我们将看看我们如何测试内置分析组件的组合,然后构建分析器以满足我们的需求。
测试内置分析组件
临时的分析器可以由内置的分析组件组成,用于测试分析配置
var analyzeResponse = client.Analyze(a => a
.Tokenizer("standard")
.Filter("lowercase", "stop")
.Text("F# is THE SUPERIOR language :)")
);
{
"tokens": [
{
"token": "f",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
很好! 这已经删除了停止的单词,但是我们仍然将F#
分词为"f"
,而没有"superior"
的"great"
同义词。
重要
我们来构建一个带有附加组件的自定义分析器来解决这个问题。
在索引中测试自定义分析器
可以在索引中创建自定义分析器,无论是创建索引还是通过更新现有索引上的设置。
添加到现有索引时,首先要关闭它。
在这个例子中,我们将添加一个自定义分析器到一个现有的索引。 首先,我们需要关闭索引
client.CloseIndex("analysis-index");
现在,我们可以更新设置以添加分析器
client.UpdateIndexSettings("analysis-index", i => i
.IndexSettings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("my_char_filter", m => m
.Mappings("F# => FSharp")
)
)
.TokenFilters(tf => tf
.Synonym("my_synonym", sf => sf
.Synonyms("superior, great")
)
)
.Analyzers(an => an
.Custom("my_analyzer", ca => ca
.Tokenizer("standard")
.CharFilters("my_char_filter")
.Filters("lowercase", "stop", "my_synonym")
)
)
)
)
);
并再次打开索引。我们还要等待五秒钟,使索引的状态变为绿色
client.OpenIndex("analysis-index");
client.ClusterHealth(h => h
.WaitForStatus(WaitForStatus.Green)
.Index("analysis-index")
.Timeout(TimeSpan.FromSeconds(5))
);
索引打开并准备就绪,我们来测试分析器
{
"tokens": [
{
"token": "fsharp",
"start_offset": 0,
"end_offset": 2,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "great",
"start_offset": 10,
"end_offset": 18,
"type": "SYNONYM",
"position": 3
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
在字段上测试分析器
也可以测试分析器的给定字段类型映射。 给定使用以下设置和映射创建的索引
client.CreateIndex("project-index", i => i
.Settings(s => s
.Analysis(a => a
.CharFilters(cf => cf
.Mapping("my_char_filter", m => m
.Mappings("F# => FSharp")
)
)
.TokenFilters(tf => tf
.Synonym("my_synonym", sf => sf
.Synonyms("superior, great")
)
)
.Analyzers(an => an
.Custom("my_analyzer", ca => ca
.Tokenizer("standard")
.CharFilters("my_char_filter")
.Filters("lowercase", "stop", "my_synonym")
)
)
)
)
.Mappings(m => m
.Map<Project>(mm => mm
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Analyzer("my_analyzer")
)
)
)
)
);
name
字段上的分析器可以用
var analyzeResponse = client.Analyze(a => a
.Index("project-index")
.Field<Project>(f => f.Name)
.Text("F# is THE SUPERIOR language :)")
);
具有说明的高级细节
通过在请求中设置Explain()
可以获得有关分析器ss的更多高级细节。
对于这个例子,我们将使用Object Initializer语法而不是Fluent API; 选择对你最适合的!
var analyzeRequest = new AnalyzeRequest
{
Analyzer = "standard",
Text = new [] { "F# is THE SUPERIOR language :)" },
Explain = true
};
var analyzeResponse = client.Analyze(analyzeRequest);
我们现在在响应中获得更多的细节
{
"detail": {
"custom_analyzer": false,
"analyzer": {
"name": "standard",
"tokens": [
{
"token": "f",
"start_offset": 0,
"end_offset": 1,
"type": "<ALPHANUM>",
"position": 0,
"bytes": "[66]",
"positionLength": 1
},
{
"token": "is",
"start_offset": 3,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 1,
"bytes": "[69 73]",
"positionLength": 1
},
{
"token": "the",
"start_offset": 6,
"end_offset": 9,
"type": "<ALPHANUM>",
"position": 2,
"bytes": "[74 68 65]",
"positionLength": 1
},
{
"token": "superior",
"start_offset": 10,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 3,
"bytes": "[73 75 70 65 72 69 6f 72]",
"positionLength": 1
},
{
"token": "language",
"start_offset": 19,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4,
"bytes": "[6c 61 6e 67 75 61 67 65]",
"positionLength": 1
}
]
}
}
}
Elasticsearch(八)【NEST高级客户端--分析器】的更多相关文章
- Elasticsearch(八)【NEST高级客户端--Mapping映射】
要使用NEST与Elasticsearch进行交互,我们需要能够将我们的解决方案中的POCO类型映射到存储在Elasticsearch中的反向索引中的JSON文档和字段.本节介绍NEST中可用的所有不 ...
- Elasticsearch Java高级客户端
1. 概述 Java REST Client 有两种风格: Java Low Level REST Client :用于Elasticsearch的官方低级客户端.它允许通过http与Elastic ...
- 使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索
使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索 2015-03-26 dotNET跨平台 最近几年出现的云计算为组织和用户带来了福音.组织对客户的了解达到前所未有的透彻, ...
- Elasticsearch系列(五)----JAVA客户端之TransportClient操作详解
Elasticsearch JAVA操作有三种客户端: 1.TransportClient 2.JestClient 3.RestClient 还有种是2.3中有的NodeClient,在5.5.1中 ...
- 【Elasticsearch】.NetCore中Elasticsearch组件NEST的使用
.NetCore中Elasticsearch组件NEST的使用 1. 安装Docker # 安装Docker curl -fsSL https://get.docker.com | bash -s d ...
- NEST - Elasticsearch 的高级客户端
NEST - High level client Version:5.x 英文原文地址:NEST - High level client 个人建议:学习 NEST 的官方文档时,按照顺序进行,不宜跳来 ...
- ElasticSearch.net NEST批量创建修改删除索引完整示例
本示例采用Elasticsearch+Nest 网上查了很多资料,发现用C#调用Elasticsearch搜索引擎的功能代码很分散,功能不完整,多半是非常简单的操作,没有成型的应用示例.比如新增或修改 ...
- ELK 之二:ElasticSearch 和Logstash高级使用
一:文档 官方文档地址:1.x版本和2.x版本 https://www.elastic.co/guide/en/elasticsearch/guide/index.html 硬件要求: 1.内存,官方 ...
- ElasticSearch(八)Elasticsearch-head 连接不上Elasticsearch的原因和解决方案
在上篇博文里ElasticSearch(七) Elasticsearch在Centos下搭建可视化服务中已经访问到了可视化界面.然后兴奋地进行了数据提交测试,提交啊,刷新啊,就是看不到数据变化,仔细一 ...
随机推荐
- 解决MongoDB分页查询之count查询慢的问题
一.概述 问题描述:在项目中优化动态查询分页接口时,发现count查询很慢(数据量大概30万),那如何解决这个问题呢? 解决方法:添加索引,多个查询条件可以添加复合索引 二.测试对比 1. 未加索引时 ...
- JS是面向过程、面向对象还是基于对象?面向对象的代码体现
一.问题 javascript是面向对象的,还是面向过程的?基于对象是什么意思? 对象: 指的是对某一类事物进行抽象,抽象出这一类事物共同的特征以及行为(也就是属性和方法),那些拥有这一共同属性和方法 ...
- Weblogic的中的文件上传
在weblogic中在jsp页面中this.getServletContext().getRealPath("/upload")这样的写法是要报错的在jsp页面总你甚至不能使用th ...
- ubuntu12.04安装nox-classic
Setup Nox repo for ânox-dependenciesâ package $ cd /etc/apt/sources.list.d/ $ wget http://openfl ...
- 从Objective-C到Swift 单例模式
在Objective-C中经常会用到单例模式.最常见的就是: [UIApplication sharedApplication].delegate 这里的sharedApplication就是一个返回 ...
- 看图说说Sun HotSpot虚拟机对象
- (字符串 键盘转换)Convert QWERTY to Dvorak -- zoj -- 5526
链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5526 Time Limit: 2 Seconds Memor ...
- [转]构建基于WCF Restful Service的服务
本文转自:http://www.cnblogs.com/scy251147/p/3566638.html 前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添 ...
- 在改变某一项目的svn的地址,relocate
不要忘记删除原有.svn文件.
- 在盒子(2CCC)的日子
在盒子(2CCC)的日子 DELPHIER的足迹印在DFW,印在2CCC.曾经的DFW和2CCC,学术气氛非常浓烈.有人提问,众人纷纷热心解答,仿佛是在解答自己难题.大家只为技术争的面红耳赤.很怀念当 ...