zoukankan      html  css  js  c++  java
  • Elasticsearch——分词器对String的作用

    更多内容参考:Elasticsearch学习总结

    关于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的全部文档。

    对于不分词的字段:

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

  • 相关阅读:
    使用 suspend 和 resume 暂停和恢复线程
    在 Go 语言中使用 Session(一)
    理解Cookie和Session
    Go Iris 中间件
    Go 通道(channel)与协程间通信
    Java终止线程的三种方式
    Go http包执行流程
    Java项目服务器跨域设置
    mysql5.7初始化密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before
    记录下在阿里云linux上安装与配置Mysql
  • 原文地址:https://www.cnblogs.com/xing901022/p/5235993.html
Copyright © 2011-2022 走看看