Elasticsearch——分词器对String的作用

关于String类型——分词与不分词

在Elasticsearch中String是最基本的数据类型,如果不是数字或者标准格式的日期等这种很明显的类型,其他的一般都会优先默认存储成String。同样的数据类型,Elasticsearch也提供了多种存储与分词的模式,不同的模式应用于不同的场景。

很多人在初次使用Elasticsearch时,都会很纳闷...

  • 为什么我存储的一句话,却查询不到?
  • 为什么我输入了汉语单词,只能一个字一个字的匹配?
  • 为什么我的url查询不到?

等等,这些都与是否分词、使用什么分词器有关。

首先说说什么是分词器吧! 比如我爱你中国

如果是标准分词器,会把它拆分成,“我”,“爱”,“你”,“中”,“国”。
如果使用一些汉语的分词器,则会分析成,“我”,“爱”,“你”,“中国”。

由于倒排索引都是以词Term为索引的,因此如果分解成了一个一个的词,查询“中国”的时候,中国也会被分解成“中”“国”,这样就可能误差到”发展中国家“这样的词。

再说说Elasticsearch中的分词器吧!

不光是在索引文档(把数据导入到Elasticsearch中),在查询的时候也需要分词器。只有索引和查询的时候使用相同的分词器,才能查询出正确的结果。

但是有时候,我们并不想把一串String给分析,想把它当做一个完整的词。比如

  • www.baidu.com
  • 吉林省 长春市 卫星路 6543号

此时,只要设置字段为不分析,就可以了。这时需要自定义下映射,因为默认String就是分析的,而且使用的是标准分词器。

准备工作

先建立一个索引

curl -XPUT localhost:9200/abc

然后定义映射,注意:只有刚刚新建、还没有任何数据的索引,才能定义映射。定义映射Mapping可以使用_mapping RESTAPI,符合下面的标准语法:

curl -XPUT localhost:9200/索引名称/类型名称/_mapping?pretty -d '{"类型名称":{"properties":{"字段名称":{"type":"字段类型","store":"是否存储","index":"索引方式、是否分析"}}}}'

比如,其中str1为String类型不分析;其他的字段str2为默认配置,就不用设置了。

curl -XPUT localhost:9200/abc/abc/_mapping?pretty -d '{"abc":{"properties":{"str1":{"type":"string","index":"not_analyzed"}}}}'

然后添加两条数据:

curl localhost:9200/abc/abc?pretty -d '{"str1":"hello, world!","str2":"goodbye! world"}'
{
  "_index" : "abc",
  "_type" : "abc",
  "_id" : "AVM2vRQgJmh5lL1r79nv",
  "_version" : 1,
  "created" : true
}

curl localhost:9200/abc/abc?pretty -d '{"str1":"hello","str2":"world"}'             {
  "_index" : "abc",
  "_type" : "abc",
  "_id" : "AVM2vbbqJmh5lL1r79nw",
  "_version" : 1,
  "created" : true
}

分析的String如何查询

如果查询的单个词,分词的字段可以使用term进行查询,如下所示:如果查询的是一个单独的词,那么会返回包含它或者等于它的目标文档。

curl -XPOST localhost:9200/abc/_search?pretty -d '{"query":{"term":{"str2":"world"}}}'
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5945348,
    "hits" : [ {
      "_index" : "abc",
      "_type" : "abc",
      "_id" : "AVM2vbbqJmh5lL1r79nw",
      "_score" : 0.5945348,
      "_source":{"str1":"hello","str2":"world"}
    }, {
      "_index" : "abc",
      "_type" : "abc",
      "_id" : "AVM2vRQgJmh5lL1r79nv",
      "_score" : 0.37158427,
      "_source":{"str1":"hello, world!","str2":"goodbye! world"}
    } ]
  }
}

不分析的String如何查询

如果字段是不分词的,而查询的是这个字段里面的一个词,那么使用term时无法查询到目标文档的。

$ curl -XPOST localhost:9200/abc/_search?pretty -d '{"query":{"term":{"str1":"hello"}}}'
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "abc",
      "_type" : "abc",
      "_id" : "AVM2vbbqJmh5lL1r79nw",
      "_score" : 1.0,
      "_source":{"str1":"hello","str2":"world"}
    } ]
  }
}

使用term查询,如果该字段是不分词,只有完整的输入目标字段,才能正确的匹配。

curl -XPOST localhost:9200/abc/_search?pretty -d '{"query":{"term":{"str1":"hello, world!"}}}'
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "abc",
      "_type" : "abc",
      "_id" : "AVM2vRQgJmh5lL1r79nv",
      "_score" : 1.0,
      "_source":{"str1":"hello, world!","str2":"goodbye! world"}
    } ]
  }
}

总结

对于分词的字段:

1 如果查询的是单个词,则查询到包含它的文档,返回结果与匹配程度有关
2 如果查询的是一段能被分析的话,比如hello world。那么查询的结果是包含分析得出的词的文档,即包含helloworld的全部文档。

对于不分词的字段:

只有查询的是 目标字段的精确值,才能匹配。

本文转自博客园xingoo的博客,原文链接:Elasticsearch——分词器对String的作用,如需转载请自行联系原博主。

时间: 2024-10-13 11:31:24

Elasticsearch——分词器对String的作用的相关文章

如何在Elasticsearch中安装中文分词器(IK+pinyin)

如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. 这是因为使用了Elasticsearch中默认的标准分词器,这个分词器在处理中文的时候会把中文单词切分成一个一个的汉字,因此引入中文的分词器就能解决这个问题. 本篇文章按照下面的内容进行描述: 分词器的作用 安装IK 简单的测试 模拟测试 安装elasticsearch-analysis-piny

elasticsearch 2.3.4 java API 连接,ik分词器,设置集群节点,创建index,mapping的几种方式

1.默认集群连接 Client client = TransportClient.builder().build() .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)); 2.自定义集群连接 Settings settings = Settings.settingsBuilder().put("cluster.name", &qu

使用 Elasticsearch 的 NGram 分词器处理模糊匹配

接到一个任务:用 Elasticsearch 实现搜索银行支行名称的功能.大概就是用户输入一截支行名称或拼音首字母,返回相应的支行名称.比如,用户输入"工行"或者"gh",我需要返回"工行XXX分行"类似这样的结果. 我心里嘀咕着:数据库不是支持通配符查询吗?为什么不直接用数据库查询? 说归说,但是任务还是要完成的.之前有在网上看过一篇文章,主要就是说用 Elasticsearch 处理通配符查询不太适合,然后我在评论中看到作者推荐了一个分词器

跟益达学Solr5之使用IK分词器

   在Solr中该如何使用IK分词器呢,这是小伙伴们问的频率比较高的一个问题,今晚特此更新此篇博客.其实之前我在其他博客里已经使用了IK分词器,只是我没做详细说明.        在schema.xml配置中其实有很多关于分词器的配置示例,我从中摘录一段配置示例,比如: Xml代码   <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100&qu

Lucene 3.6.2入门(5) 自定义停用词分词器和同义词分词器

首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.toke

Lucene 3.6.2入门(4) 中文分词器

package com.jadyer.lucene; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.SimpleAnalyzer; import org.apache.lucene.analysis.StopAnalyzer; import org.apache.lucene

使用肖波的KTDictSeg分词器 为Lucene.net服务

最近在看Lucene.net 发现Lucene.net的中文分词资料不是很多,很早就在看肖波的KTDictSeg,觉的分词效果不错,但是没有lucene接口,看他的blog也是很长时间没有更新了 他在他的blog中提到将在下一个版本中提供对lucene的支持,我这里期待中...同时blog中提到一挥的修改版本,但是一挥的站打不开了,不知道什么原因,我刚刚看这个时间不长,查了些资料 写了下面的代码实现了KTDictSeg在Lucene.net中的调用,期待有更好的方法出现 下面附上代码 1usin

Lucene5学习之使用MMSeg4j分词器

     MMSeg4j是一款中文分词器,详细介绍如下:        1.mmseg4j 用 Chih-Hao Tsai 的 MMSeg 算法(http://technology.chtsai.org/mmseg/ )实现的中文分词器,并实现 lucene 的 analyzer 和 solr 的TokenizerFactory 以方便在Lucene和Solr中使用.          2.MMSeg 算法有两种分词方法:Simple和Complex,都是基于正向最大匹配.Complex 加了四

Solr配置中文分词器IKAnalyzer及增删改查调用

一.配置IKAnalyzer中文分词器 Solr 版本5.2.1 IKAnalyzer2012_u6.jar报错 ,用IKAnalyzer2012_FF_hf1.jar 替换可解决 解决lucene4.0与IKAnalyzer的冲突.解决Exception in thread "main" java.lang.VerifyError: class org.wltea.analyzer.lucene.IKAnalyzer overrides final method tokenStrea