IK 分詞器

Juno3550發表於2022-01-09


IK 分詞器-介紹

現有問題:ES 預設對中文分詞並不友好,實際上是把中文進行了每個字的分詞。

# 檢視ES對中文的預設分詞
GET /_analyze
{
  "analyzer": "standard",
  "text": "乒乓球明年總冠軍"
}

# 分詞結果,是將“乒乓球明年總冠軍”拆分成了“乒”、“乓”、“球”、“明”、“年”、“總”、“冠”、“軍”

對此,通常我們需要為 ES 加入友好的中文分詞器,如 IKAnalyzer


IK 分詞器-安裝

環境準備:Maven

ElasticSearch 要使用 IK,就要先構建 IK 的 jar 包,這裡要用到 Maven 包管理工具,而 Maven 需要 Java 環境,而 ElasticSearch 內建了 JDK, 所以可以將 JAVA_HOME 設定為ElasticSearch 內建的 JDK 。

1)設定 JAVA_HOME

vi /etc/profile
# 在profile檔案末尾新增
#java environment
export JAVA_HOME=/opt/elasticsearch-7.4.0/jdk
export PATH=$PATH:${JAVA_HOME}/bin

# 儲存退出後,重新載入profile
source /etc/profile

2)下載 Maven 安裝包

wget https://mirrors.aliyun.com/apache/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz 

3)解壓 Maven 安裝包

tar xzf apache-maven-3.1.1-bin.tar.gz 

4)設定軟連線

ln -s apache-maven-3.1.1 maven 

5)設定 path

  • 開啟檔案:
vi /etc/profile.d/maven.sh
  • 將下面的內容複製到檔案,儲存:
export MAVEN_HOME=/opt/maven  
export PATH=${MAVEN_HOME}/bin:${PATH} 
  • 設定好 Maven 的路徑之後,需要執行下面的命令使其生效:
source /etc/profile.d/maven.sh

6)驗證 Maven 是否安裝成功

mvn -v

7)將 Maven 映象下載換成阿里雲

vi /opt/apache-maven-3.1.1/conf/setting.xml
	<mirror>
        <id>alimaven</id>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <mirrorOf>central</mirrorOf>
    </mirror>

安裝 IK 分詞器

1)下載 IK

wget https://github.com/medcl/elasticsearch-analysis-ik/archive/v7.4.0.zip

2)解壓 IK

# 如果本機環境沒有安裝 unzip
yum install zip 
yum install unzip
# 解壓 IK
unzip v7.4.0.zip

3)編譯 jar 包

# 切換到 elasticsearch-analysis-ik-7.4.0目錄
cd elasticsearch-analysis-ik-7.4.0/
#打包
mvn package

4) jar 包移動

  • package 執行完畢後會在當前目錄下生成 target/releases 目錄,將其中的 elasticsearch-analysis-ik-7.4.0.zip 拷貝到 ElasticSearch 目錄下的新建的目錄 plugins/analysis-ik,並解壓:
#切換目錄
cd /opt/elasticsearch-7.4.0/plugins/
#新建目錄
mkdir analysis-ik
cd analysis-ik
#執行拷貝
cp -R /opt/elasticsearch-analysis-ik-7.4.0/target/releases/elasticsearch-analysis-ik-7.4.0.zip /opt/elasticsearch-7.4.0/plugins/analysis-ik
#執行解壓
unzip /opt/elasticsearch-7.4.0/plugins/analysis-ik/elasticsearch-analysis-ik-7.4.0.zip

5)拷貝辭典

  • 將 elasticsearch-analysis-ik-7.4.0目錄下的 config 目錄中的所有檔案拷貝到 elasticsearch 的 config 目錄:
cp -R /opt/elasticsearch-analysis-ik-7.4.0/config/* /opt/elasticsearch-7.4.0/config

6)重啟 ElasticSearch


IK 分詞器-使用

分詞效果

IK 分詞器有兩種分詞模式:ik_max_wordik_smart 模式

# ik_max_word:會將文字做最細粒度的拆分。
GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "乒乓球明年總冠軍"
}
# 分詞結果:“乒乓球”、“乒乓”、“球”、“明年”、“總冠軍”、“冠軍”

# ik_smart:會做最粗粒度的拆分
GET /_analyze
{
  "analyzer": "ik_smart",
  "text": "乒乓球明年總冠軍"
}
# 分詞結果:“乒乓球”、“明年”、“總冠軍”

由結果看出,IK 的分詞效果達到我們對中文分詞的要求。


查詢文件

  • 詞條查詢(term):詞條查詢不會分析查詢條件,只有當詞條和查詢字串完全匹配時才匹配搜尋。

  • 全文查詢(match):全文查詢會分析查詢條件,先將查詢條件進行分詞,然後查詢,求並集。

案例

# 建立索引,新增對映,並指定分詞器為IK分詞器
PUT person2
{
  "mappings": {
    "properties": {
      "name": {  # 沒指定則使用預設分詞器"standard"
        "type": "keyword"
      },
      "address": {
        "type": "text",
        "analyzer": "ik_max_word"  # 指定分詞器
      }
    }
  }
}

# 新增文件
POST /person2/_doc/1
{
  "name":"張三",
  "age":18,
  "address":"北京海淀區"
}

POST /person2/_doc/2
{
  "name":"李四",
  "age":18,
  "address":"北京朝陽區"
}

POST /person2/_doc/3
{
  "name":"王五",
  "age":18,
  "address":"北京昌平區"
}

# 查詢對映
GET person2

image

查詢分詞結果

GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "北京昌平"
}
  • 查詢結果
{
  "tokens" : [
    {
      "token" : "北京",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "昌平",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    }
  ]
}

詞條查詢(term)

詞條查詢不會分析查詢條件,只有當詞條和查詢字串完全匹配時才匹配搜尋。

  • 示例:查詢“北京”
GET /person2/_search
{
  "query": {
    "term": {
      "address": {
        "value": "北京"
      }
    }
  }
}
  • 查詢結果
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.13786995,
    "hits" : [
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.13786995,
        "_source" : {
          "name" : "李四",
          "age" : 18,
          "address" : "北京朝陽區"
        }
      },
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.13786995,
        "_source" : {
          "name" : "王五",
          "age" : 18,
          "address" : "北京昌平區"
        }
      },
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.12562492,
        "_source" : {
          "name" : "張三",
          "age" : 18,
          "address" : "北京海淀區"
        }
      }
    ]
  }
}
  • 示例:查詢“北京昌平”
GET /person2/_search
{
  "query": {
    "term": {
      "address": {
        "value": "北京"
      }
    }
  }
}
  • 查詢結果
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

全文查詢(match)

# 全文查詢會分析查詢條件,先將查詢條件進行分詞,然後查詢,求並集
GET /person2/_search
{
  "query": {
    "match": {
      "address":"北京昌平"
    }
  }
}

查詢結果

{
  "took" : 83,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.1505673,
    "hits" : [
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.1505673,
        "_source" : {
          "name" : "王五",
          "age" : 18,
          "address" : "北京昌平區"
        }
      },
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.13786995,
        "_source" : {
          "name" : "李四",
          "age" : 18,
          "address" : "北京朝陽區"
        }
      },
      {
        "_index" : "person2",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.12562492,
        "_source" : {
          "name" : "張三",
          "age" : 18,
          "address" : "北京海淀區"
        }
      }
    ]
  }
}

相關文章