ElasticSearch(2)

搭建Elasticsearch集群

可以复制,但复制的时候注意把包里面的data删掉,否则几个里面的索引都一样,都有主分片,那么互相不承认对方,集群就不会生效了。

配置文件elasticsearch.yml需要修改,把下列配置放开:

cluster.name: dianping-app
node.name: node-1
network.host: 127.0.0.1

#对外端口
http.port: 9200

#集群间通信
transport.tcp.port: 9300

#允许跨域
http.cors.enabled: true
http.cors.allow-origin: "*"

#用来发现集群的节点
discovery.seed_hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"]

#哪些节点有资格竞选master
cluster.initial_master_nodes: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"]

其他节点的配置,修改name和两个端口号即可。分别运行后,看一下节点:

 创建一个索引:

PUT /test
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 2
  }
}

这里我运行了3个,创建后是green

如果把主分片变成10呢?

那么把从分片变成3呢?

 由此可以看出,es在主分片的创建上,可以在一个节点创建多个,但是从分片必须和主分片与其他从分片的节点分开。

基础语法

新建索引

分为结构化和非结构化

非结构化新建索引及删改查:非结构化是指在创建索引的时候不定义索引的mapping格式,类比数据库就是不定义表结构,在创建的时候会自动分析索引的结构,自动生成mapping结构。

写法:

PUT /employee/_doc/1
{
  "name":"耗子",
  "age":18
}

运行后会提示:

就创建好了。

还可以先setting,再创建值:

PUT /employee
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 2
  }
}

PUT /employee/_doc/1
{
  "name":"耗子",
  "age":18
}

还可以做修改操作,把name改一下

运行结果:

可以看到,created变成了updated。所以PUT在所以没有id=1的时候,完成创建操作,如果已经存在这个id,就变成了更新操作了,并且version会+1。

查询的话用GET,例如:GET /employee/_doc/1即可。

需要注意的是上面的PUT是全量修改的,也就是说覆盖,在put的时候不管需不需要修改的字段都需要写上面。那么有全量修改,当然也会对应着有指定字段的修改。往下看

//指定字段修改
POST /employee/_update/1
{
  "doc":{
    "name":"耗子3"
  }
}

GET看一下结果:

那么对于上面的put而言,是如果没有就创建,如果有就覆盖,那么如果想实现如果有就创建失败怎么办?

//强制指定创建,若已存在,则失败
POST /employee/_create/1
{
  "name":"123",
  "age":19
}

如果有,运行结果:

如果要删除某个文档,DELETE

DELETE /employee/_doc/1

查询全部文档呢?当然用search如果不给条件的话,es不会查询全部文档,会分页,具体详情后面讲复杂查询的时候再说。

GET /employee/_search

再在kibana上看下索引的结构:

结构化新建索引: 

 因为是非结构化创建,所以es会跟去情况创建mapping,有时候es创建的mapping跟我们想要的并不一样,所以绝大多数情况下,还是要结构化创建的。

//使用结构化的方式创建索引
PUT /employee
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "integer"
      }
    }
  }
}

看一下kibana

 接下来看看分页查询

//分页查询
GET /employee/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 1
}

这个分页查询的from和size很好懂,不解释了。

看一下带条件的查询

//带关键字条件查询
GET /employee/_search
{
  "query": {
    "match": {
      "name": "耗子1"
    }
  }
}

查询结果:

改一下关键字,name改成小子,结果还是能查出来:

这就是es相较于传统数据库like查询的不同了。原理是在es没有设置分词器的时候,es默认会把中文每个字都分开,所以“子”就匹配上了。
带排序的查询:

//带排序
GET /employee/_search
{
  "query": {
    "match": {
      "name": "小子"
    }
  },
  "sort":[
    {
      "age":{"order":"desc"}
    }
  ]
}

过滤查询

//带过滤
GET /employee/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term":{"age":18}
        }
      ]
    }
  }
}

 其中term相当于词的精确匹配,而match相当于分词匹配。

带聚合的查询:

//带聚合
GET /employee/_search
{
  "query": {
    "match": {
      "name": "小子"
    }
  },
  "sort":[
    {
      "age":{"order":"desc"}
    }
  ],
  "aggs": {
    "group_by_age": {
      "terms": {
        "field": "age"
      }
    }
  }
}

运行结果最后会加记录,通过年龄进行了统计:

高级语法

相对于基本语法,高级语法更注重分词的应用。

写个小查询demo

PUT /movie/_doc/1
{
  "name":"Eating an apple a day & keeps the doctor away"
}

GET /movie/_search
{
  "query": {
    "match": {
      "name": "eat"
    }
  }
}

先新建一个索引,然后查询eat,查询结果是空的

按说在英文中,eating和eat应该是一样的,但是这里是空的,因为这是分词器自己分的,我们想知道分词器怎么分的,那就要看下分词器了:

GET /movie/_analyze
{
  "field": "name",
  "text": "Eating an apple a day & keeps the doctor away"
}

可以看到:

对于人脑来说,eating和eat可能是同样的,但是对于及其来说,肯定是不一样的。

接下来说下analyze分词处理的过程:

首先文字过来以后,先经过字符过滤器,把标点符号之类的过滤掉,然后进入分词器,如果没有指定分词器的话,es会使用标准的字符处理器,这种处理器会使用空格和标点符号做分割,分割后会变成若干个单词,再进行分词过滤,在标准处理器中的过滤就是变小写。

接下来解决这样一个问题,那么就是在创建索引的时候指定分词器:

//使用结构化的方式创建索引
PUT /movie
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "name":{
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}


PUT /movie/_doc/1
{
  "name":"Eating an apple a day & keeps the doctor away"
}

再查询eat,结果:

接下来还是用analyze查询一下分词情况

可以看到有很大的不同。

这里首先会把a/an/the这样的词去掉,因为英文分词器会认为这些词是没有意义的,对于英文分词器来说,他的分词过程:

字符过滤器(这里不仅过滤字符,还会过滤a/an/the这种词)->字符处理(跟之前一样,分开单词)->分词过滤(重点在这里,英文分词器会把单复数考虑进去,然后从中提炼出词干,例如day的词干就变成了dai,后面也都是一样的)。这样,无论是搜索eat还是apples,都能搜索到。

Elasticsearch字段类型

Text:可被分析索引的字符串类型

Keyword:不可被分析、只能被精确匹配的字符串类型

Date:日期类型,可以配合dateformat一起使用

数字类型:long、integer、short、double等

boolean:true、false

Array:["one","two"]

Object:可用json嵌套来描述

ip类型

Geo_point:地理位置,也就是经纬度

发布了97 篇原创文章 · 获赞 28 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/haozi_rou/article/details/104705023