天天看點

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

。那麼查詢的結果是包含分析得出的詞的文檔,即包含

hello

world

的全部文檔。

對于不分詞的字段:

隻有查詢的是 目标字段的精确值,才能比對。

作者:xingoo

出處:http://www.cnblogs.com/xing901022

本文版權歸作者和部落格園共有。歡迎轉載,但必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接!

繼續閱讀