Elasticsearch全文检索

简介

  Elasticsearch是一个实时分布式搜索和分析引擎,用于全文搜索、结构化搜索、分析以及将这三者混合使用。Elasticsearch实现全文索引,需要使用分词器,默认使用的standard分词器。由于本文介绍的是中文的全文检索,因此我们需要使用第三方插件的中文分词器,如ik分词器、mmsegf分词器,在此我们主要使用的是ik分词器。

安装ik分词器

1.首先,我们需要根据Elasticsearch的版本来选择使用哪一个版本的ik分词器,如下:

IK versionES version
master2.2.0->master
1.8.02.2.0
1.7.02.1.1
1.6.12.1.0
1.5.02.0.0
1.4.11.7.2

由于我们的Elasticsearch的版本为1.7.3,因此我们使用ik-1.4.1。

wget https://github.com/medcl/elasticsearch-analysis-ik/archive/v1.4.1.tar.gz
tar -zxvf v1.4.1.tar.gz 
cd elasticsearch-analysis-ik-1.4.1
cp -rf /home/test/ELKstack/elasticsearch-analysis-ik-1.4.1/config/ik /usr/local/elasticsearch-1.7.3/config
#需要安装maven并配置环境变量
vim /etc/profile
export MAVEN_HOME=/usr/local/maven
export PATH=${PATH}:${MAVEN_HOME}/bin
export M2_REPO=/usr/local/maven/repository
#安装
mvn package
#安装完毕后,将其放到elasticsearch的插件目录下
unzip /home/test/ELKstack/elasticsearch-analysis-ik-1.4.1target/releases/elasticsearch-analysis-ik-1.4.1.zip -d /usr/local/elasticsearch-1.7.3/plugins/ik

2.配置elasticsearch.yml

vim /usr/local/elasticsearch-1.7.3/config/elasticsearch.yml
index:
  analysis:
    analyzer:
      ik:
          alias: [ik_analyzer]
          type: org.elasticsearch.index.analysis.IkAnalyzerProvider
      ik_max_word:
          type: ik
          use_smart: false
      ik_smart:
          type: ik
          use_smart: true
或者
index.analysis.analyzer.ik.type : "ik"

以上两种配置方式的区别:
(1)、第二种方式,只定义了一个名为 ik 的 analyzer,其 use_smart 采用默认值 false

(2)、第一种方式,定义了三个 analyzer,分别为:ik、ik_max_word、ik_smart,其中 ik_max_word 和 ik_smart 是基于 ik 这个 analyzer 定义的,并各自明确设置了 use_smart 的不同值。

(3)、其实,ik_max_word 等同于 ik。ik_max_word 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各的组合;而 ik_smart 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。

因此,建议,在设置 mapping 时,用 ik 这个 analyzer,以尽可能地被搜索条件匹配到。

3.重启elasticsearch

/etc/init.d/elasticsearch start

检查日志查看ik插件是否加载成功。

分词测试

1.创建索引

curl -XPOST http://10.10.20.16:9200/index

2.创建mapping

curl -XPOST http://10.10.20.16:9200/index/test/_mapping?pretty -d '
{
  "test":{
           "properties":{
              "NewString":{"type":"string","indexAnalyzer":"ik","searchAnalyzer":"ik"},
              "OriginString":{"type":"string","indexAnalyzer":"ik","searchAnalyzer":"ik"},
              "townname":{"type":"string","indexAnalyzer":"ik","searchAnalyzer":"ik"},
              "distname":{"type":"string","indexAnalyzer":"ik","searchAnalyzer":"ik"},
              "haclcode":{"type":"string"},
              "towncode":{"type":"string"},
              "distcode":{"type":"string"},
              "WordClass":{"type":"string"},
              "WordCode":{"type":"string"},
              "x":{"type":"float"},
              "y":{"type":"float"}
          }
    }
}'

若在后期添加新字段,需要更新mapping

curl -XPUT http://10.10.20.16:9200/index/_mapping/test -d '
 {
    "properties":{
        "OriginString":{
           "type":"string",
           "indexAnalyzer":"ik",
           "searchAnalyzer":"ik"
          }
      }
 }'

3.导入数据
导入数据使用bulk api,处理海量数据时会极大的提高效率。
bulk api的请求格式为:

{ action: { metadata }}\n
{ request body        }\n
{ action: { metadata }}\n
{ request body        }\n

这种格式就类似于一个用”\n”字符来连接的单行json一样。
因此使用bulk api需要将我们的原始数据格式化为上面的json格式。
例如:
我们的原始数据为:

CL029103CHY4064 城阳职教中心    ha      指教中心        CHY     城阳区  null    null    120.38120840204475      36.30916300197122       ed
CL029103CHY4064 城阳职教中心    ha      明阳路职教      CHY     城阳区  null    null    120.38120840204475      36.30916300197122       ed
CL029103CHY4064 城阳职教中心    ha      职教中心        CHY     城阳区  null    null    120.38120840204475      36.30916300197122       ed

通过python进行格式化:

vim format.py 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
names = ['WordCode', 'NewString', 'WordClass', 'OriginString', 'distcode', 'distname', 'towncode', 'townname', 'x', 'y', 'haclcode']

with open('/home/test/text', 'r') as f:
        data = f.readlines()

s = '{"index":{"_index":"index","_type":"test"}}'

for line in data:
        values = line.strip().split()
        dictionary = dict(zip(names, values))
        #格式化为json
        #解决list,dict乱码
        json_data = json.dumps(dictionary).decode("unicode-escape")
        with open('/home/test/out', 'a') as f1:
                print >> f1, s
        with open('/home/test/out', 'a') as f2:
                print >> f2, json_data.encode("utf-8")

格式化后的out文件为:

{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "指教中心", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}
{"index":{"_index":"test","_type":"supersearch"}}
{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "明阳路职教", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}
{"index":{"_index":"test","_type":"supersearch"}}
{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "职教中心", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}

导入数据

curl http://10.10.20.16:9200/index/_bulk?pretty --data-binary @out

注意:out文件的json格式,每行后面必须跟\n
4.检索数据

全字段查询

curl -XPOST  http://10.10.20.16:9200/index/test/_search?pretty  -d'
{
    "query" : { "match" : { "_all" : "职教" }}
}'

_all字段在新字段探索阶段比较管用,当你还不清楚文档的最终结构时,可以将任何查询用于这个字段。

精确查询

curl -XPOST http://10.10.20.16:9200/index/test/_search?pretty  -d'
{
    "query" : { "term" : { "OriginString" : "职教" }}
}'
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

由于是精确匹配,不会进行分词,因此没有匹配项。

模糊查询

curl -XPOST  http://10.10.20.16:9200/index/test/_search?pretty  -d'
{
    "query" : { "match" : { "OriginString" : "职教" }}
}'
{
  "took" : 16,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 2.7033195,
    "hits" : [ {
      "_index" : "test",
      "_type" : "supersearch",
      "_id" : "AVOhG4x9J_-fAShDYmCN",
      "_score" : 2.7033195,
      "_source":{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "指教中心", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}
    }, {
      "_index" : "test",
      "_type" : "supersearch",
      "_id" : "AVOhG4x9J_-fAShDYmCM",
      "_score" : 2.5207999,
      "_source":{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "职教中心", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}
    }, {
      "_index" : "test",
      "_type" : "supersearch",
      "_id" : "AVOhG4x9J_-fAShDYmCL",
      "_score" : 2.2980154,
      "_source":{"haclcode": "ed", "townname": "null", "distname": "城阳区", "towncode": "null", "distcode": "CHY", "WordClass": "ha", "OriginString": "明阳路职教", "y": "36.30916300197122", "x": "120.38120840204475", "WordCode": "CL029103CHY4064", "NewString": "城阳职教中心"}
    }]
   }
}

多词查询

curl -XPOST  http://10.10.20.16:9200/index/test/_search?pretty  -d'
{
    "query" : { "match" : { "OriginString" : {"query":"城阳 中心","operator":"and" }}}
}'

跨字段查询

curl -XPOST  http://10.10.20.16:9200/index/test/_search?pretty  -d'
{
    "query" : { "multi_match" : { "query":"职教中心","fields":["OriginString","NewString"]} }
}'

总结

  Elasticsearch的全文检索功能我们介绍的只是入门,有好多细节性的东西需要我们在测试或使用过程中慢慢去了解,如结构化查询、过滤操作,都可以帮助我们有效分析数据文件。另外,此处我们是将数据库的导出到文本文件,然后自行格式化为bulk适用的json格式,在生产环境中我们也可以借助相关插件,直接将数据库数据导入到elasticsearch中,大大提高了效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值