es入门小结

es介绍

1 es:出现是为了解决大数据量搜索的问题
2 符合resful协议,使用java封装,分布式搜索引擎
3 es概念:集群,节点,分片,副本(保证高可用),全文检索
4 把一段文章进行分词,把所有次都建立索引
5 倒排索引:根据分词对文章建立索引
6 es概念:索引,类型,文档
7 es安装:7.9.x,公司7.5
8 6.x之前 和 6.x 和7.x有区别
    -6.x之前,一个索引下可以有多个类型
    -6.x:还支持这样使用,不允许在一个索引下建多个类型
    -7.x:不支持使用,也不允许创建
9 es安装,
    -安装jdk:1.8以上
    -es安装:解压即用
    -kinaba版本要对应,官方提供,不仅仅做客户端使用,解压即用,配置文件指定连接的es服务端地址
    -es-head:第三方es客户端,node
        -npm install 
        -npm run start
        -需要在es服务端配置允许跨域
        
View Code

索引操作

# 1 对索引的增删查改
# 2 创建索引
PUT lqz2
{
  "settings": {
    "index":{
      "number_of_shards":5,
      "number_of_replicas":1
    }
  }
}
'''
number_of_shards
每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。
number_of_replicas
每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。
'''
# 3 查看索引
#获取lqz2索引的配置信息
GET lqz2/_settings
#获取所有索引的配置信息
GET _all/_settings
#同上
GET _settings
#获取lqz和lqz2索引的配置信息
GET lqz,lqz2/_settings


# 修改索引

## 不建议修改(改只能改副本的数量)
PUT lqz/_settings
{
  "number_of_replicas": 3
}
# 不允许改
PUT lqz/_settings
{
  "number_of_shards": 3
}


# 删除索引
DELETE lqz
View Code

映射管理

1 mapping type 用来创建类型(类型是表的概念)
2 映射用来定义字段的类型及相关属性
3 非关系型数据库不需要先创建类型,直接存文档,es会默认推测字段类型
4 我们来使用mapping定义,会更准确
5 字段数据类型 
    string类型:text,keyword,text会分词,keyword不分词了
    数字类型:long,integer,short,byte,double,float
    日期类型:data
    布尔类型:boolean
    binary类型:binary
    复杂类型:object(实体,对象),nested(列表)
    geo类型:geo-point,geo-shape(地理位置)
    专业类型:ip,competion(搜索建议)
    
6 映射参数
View Code
属性 描述 适合类型
store 值为yes表示存储,no表示不存储,默认为no all
index yes表示分词,no表示不分词,默认为true text
null_value 如果字段为空,可以设置一个默认值,比如"NA"(传过来为空,不能搜索,na可以搜索) all
analyzer 可以设置索引和搜索时用的分析器,默认使用的是standard分析器,还可以使用whitespace,simple。都是英文分析器 all
include_in_all 默认es为每个文档定义一个特殊域_all,它的作用是让每个字段都被搜索到,如果想让某个字段不被搜索到,可以设置为false all
format 时间格式字符串模式 date

 

 

 

 

 

 

 

 

 

 

 

7 通过映射,创建类型
    -6.x之前:

PUT books2
{
  "mappings": {
    "book":{
      "properties":{
        "title":{
          "type":"text"
        },
        "price":{
          "type":"integer"
        },
        "addr":{
          "type":"keyword"
        },
        "company":{
          "properties":{
            "name":{"type":"text"},
            "company_addr":{"type":"text"},
            "employee_count":{"type":"integer"}
          }
        },
        "publish_date":{"type":"date","format":"yyy-MM-dd"}
       
      }
    }
  }
}


        
    -7.x以后:
    # 创建索引,指定映射
    PUT books
    {
      "mappings": {
        "properties":{
          "title":{
            "type":"text"
          },
          "price":{
            "type":"integer"
          },
          "addr":{
            "type":"keyword"
          },
          "company":{
            "properties":{
              "name":{"type":"keyword"},
              "company_addr":{"type":"text"},
              "employee_count":{"type":"integer"}
            }
          },
          "publish_date":{"type":"date","format":"yyy-MM-dd"}

        }

      }
    }
    
    
    
# 类型(映射创建完成后,插入数据测试)
    # 插入文档测试
    PUT books/_doc/1
    {
      "title":"大头儿子小偷爸爸",
      "price":100,  
      "addr":"北京天安门",
      "company":{
        "name":"我爱北京天安门",
        "company_addr":"我的家在东北松花江傻姑娘",
        "employee_count":10
      },
      "publish_date":"2019-08-19"
    }

    # 再插入一条文档
    PUT books/_doc/2
    {
      "title":"白雪公主和十个小矮人",
      "price":"99",
      "addr":"黑暗森里",
      "company":{
        "name":"我的家乡在上海",
        "company_addr":"朋友一生一起走",
        "employee_count":10
      },
      "publish_date":"2018-05-19"
    }


    # 向lqz2插入文档
    PUT lqz2/_doc/1
    {
      "title":"大头儿子小偷爸爸",
      "price":100,  
      "addr":"北京天安门",
      "publish_date":"2019-08-19"
    }


# 查看映射
GET books/_mapping
GET lqz2/_mapping
# 索引查看
#查看books索引的mapping
GET books/_mapping
#获取所有的mapping
GET _all/_mapping
映射管理

文档操作

# 增加文档,不需要先创建索引和类型
PUT lqz/_doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}
# 注意点:**当执行`PUT`命令时,如果数据不存在,则新增该条数据,如果数据存在则修改该条数据
文档的增删改查
GET lqz/_doc/1
查看文档
# 替换修改
PUT lqz/_doc/1
{
  "desc":"皮肤很黄,武器很长,性格很直",
  "tags":["很黄","很长", "很直"]
}

# 局部修改
POST lqz/_update/2
{
  "doc": {
    "desc": "皮肤很黄,武器很长,性格很直",
    "tags": ["很黑","很长", "很直"]
  }
}
修改文档
DELETE lqz/_doc/4
删除文档
# 1 根据id查询
GET lqz/_doc/1
# 2 模糊查询方式一
GET lqz/_doc/_search?q=from:gu
# 3 模糊查询方式二(推荐使用)
GET lqz/_doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  }
}
查询的几种方式
1 match
    GET lqz3/_doc/_search
        {
          "query": {
            "match": {
              "from": "gu"
            }
          }
        }
2 match_all
    GET lqz3/_doc/_search
    {
      "query": {
        "match_all": {
        }
      }
    }
3 match_phrase:slop参数
    GET t1/doc/_search
    {
      "query": {
        "match_phrase": {
          "title": {
            "query": "中国世界",
            "slop": 2
          }
        }
      }
    }
4 match_phrase_prefix:只针对英文单词
GET t3/doc/_search
    {
      "query": {
        "match_phrase_prefix": {
          "desc": "bea"
        }
      }
    }



5 multi_match :多字段查询
    GET t3/doc/_search
    {
      "query": {
        "multi_match": {
          "query": "beautiful",
          "fields": ["title", "desc"]
        }
      }
    }
    
    
    
 # term查询如果要查询多个语句直接使用[]  
 GET w10/doc/_search
    {
      "query": {
        "terms": {
          "t1": ["beautiful", "sexy"]
        }
      }
    }
term与match查询
# 对结果进行排序(只能排序可以排序的字段,数字类型,日期类型)
GET lqz3/_doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  
  "sort": [
    {
      "age": {
        "order": "asc"
      }
    }
  ]
}
对查询结果进行排序
# 分页(from是从第几条取,size是取几条)
GET lqz3/_doc/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ],

  "from": 2,
  "size": 2
}
分页
#must and的条件
GET lqz3/_doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "age": 30
          }
        }
      ]
    }
  }
}

# or 条件
GET lqz3/_doc/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "tags": "闭月"
          }
        }
      ]
    }
  }
}


# 都不是
GET lqz3/_doc/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "from": "gu"
          }
        },
        {
          "match": {
            "tags": "可爱"
          }
        },
        {
          "match": {
            "age": 18
          }
        }
      ]
    }
  }
}

# 查询某个范围
GET lqz3/_doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        }
      ],
      "filter": {
        "range": {
          "age": {
            "gt": 25
          }
        }
      }
    }
  }
}


## 大于等于小于等于
GET lqz3/_doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "from": "gu"
          }
        }
      ],
      "filter": {
        "range": {
          "age": {
            "lte": 25,
            "gte":18
          }
        }
      }
    }
  }
}
布尔查询
GET lqz3/_doc/_search
{
  "query": {
    "match": {
      "name": "顾老二"
    }
  },
  "_source": ["name", "age"]
}
查询字段过滤
# 结果高亮
GET lqz3/_doc/_search
{
  "query": {
    "match": {
      "name": "石头"
    }
  },
  "highlight": {
    "pre_tags": "<b class='key' style='color:red'>",
    "post_tags": "</b>",
    "fields": {
      "name": {}
    }
  }
}
对结果高亮显示
# 聚合函数 sum,min,max,avg
GET lqz3/_doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "aggs": {
    "my_sum": {
      "sum": {
        "field": "age"
      }
    }
  },
  "_source": ["name", "age"]
}

# 分组查询
GET lqz3/_doc/_search
{
  "size": 0, 
  "query": {
    "match_all": {}
  },
  "aggs": {
    "age_group": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 15,
            "to": 20
          },
          {
            "from": 20,
            "to": 25
          },
          {
            "from": 25,
            "to": 30
          }
        ]
      }
    }
  }
}
聚合查询
1 安装中文分词
    -git上把对应版本的分词器包下载
    -解压到es的plugins目录下
    -重启es,kibana
    -创建映射时候,指定分词为中文分词即可
ik分词器

Python操作es方式一

1 mysql  user表插入数据,就要把数据同步到es中去
    -第一种方案:
        -User.object.create()
        -插入到es的代码
     -第二种方案
        -写一个插入es的函数,传入参数,就能插入
        -User.object.create()
        -调用这个函数
      -第三种方案:
        -User.object.create()
        -提交一个celery任务,异步插入
      -第四种方案:
        -信号,对象一创建就会触发一个信号
        -信号函数种判断如果是User表模型,提交一个celery任务,异步插入
        
pyes 1
from elasticsearch import Elasticsearch

obj = Elasticsearch()
# 创建索引(Index)
# result = obj.indices.create(index='user2',ignore=400)
# print(result)
# 删除索引
# result = obj.indices.delete(index='lqz5', ignore=[400, 404])
# 插入数据
# data = {'userid': '1', 'username': 'lqz','password':'123'}
# result = obj.create(index='user', doc_type='_doc', id=1, body=data)
# print(result)
# 更新数据
'''
不用doc包裹会报错
ActionRequestValidationException[Validation Failed: 1: script or doc is missing
'''
# data ={'doc':{'userid': '1', 'username': 'asdfasd','password':'sdddd','test':'test'}}
# # result = obj.update(index='user', doc_type='_doc', body=data, id=1)
# result = obj.update(index='user',  body=data, id=1)
# print(result)


# 删除数据
# result = obj.delete(index='user', id=1)
# print(result)

# 查询
# 查找所有文档
# query = {'query': {'match_all': {}}}
#  查找名字叫做jack的所有文档
# query = {'query': {'match': {'name': '大娘子'}}}
query={
  "query": {
    "match_phrase": {
      "title": {
        "query": "中国世界",
        "slop": 2
      }
    }
  }
}

# 查找年龄大于11的所有文档
query = {'query': {'range': {'age': {'gte': 30}}}}

allDoc = obj.search(index='lqz3', body=query)
print(allDoc)
# print(allDoc['hits']['hits'][0]['_source'])
model

Python操作es方式二

from datetime import datetime
from elasticsearch_dsl import Document, Date, Nested, Boolean,analyzer, InnerDoc, Completion, Keyword, Text,Integer

from elasticsearch_dsl.connections import connections

# 连接es
connections.create_connection(hosts=["localhost"])


# Article映射,两个字段
# title是Text类型,分词器使用ik_max_word
class Article(Document):
    title = Text(analyzer='ik_max_word', search_analyzer="ik_max_word", fields={'title': Keyword()})
    author = Text()

    class Index:
        name = 'myindex'  # 指定索引名

    def save(self, ** kwargs):

        return super(Article, self).save(** kwargs)


if __name__ == '__main__':
    # Article.init()  # 创建映射
    # # 保存数据
    # article = Article()
    # article.title = "Go语言测试Python"
    # article.save()  # 数据就保存了

    #查询数据
    # s=Article.search()
    # s = s.filter('match', title="测试")
    #
    # results = s.execute()
    # print(results)
    # for article in results:
    #     print(article.title)

    #删除数据
    # s = Article.search()
    # s = s.filter('match', title="测试").delete()

    #修改数据
    s = Article().search()
    s = s.filter('match', title="测试")
    results = s.execute()
    print(results[0])
    results[0].title="xxx"
    results[0].save()
View Code

es集群搭建两种方式

- 广播
#1 在本地单独的目录中,再复制一份elasticsearch文件
# 2 分别启动bin目录中的启动文件
# 3 在浏览器里输入:http://127.0.0.1:9200/_cluster/health?pretty
    -通过number_of_nodes可以看到,目前集群中已经有了两个节点了

- 单播
#现在,我们为这个集群增加一些单播配置,打开各节点内的\config\elasticsearch.yml文件。每个节点的配置如下(原配置文件都被注释了,可以理解为空,我写好各节点的配置,直接粘贴进去,没有动注释的,出现问题了好恢复):

#1 elasticsearch1节点,,集群名称是my_es1,集群端口是9300;节点名称是node1,监听本地9200端口,可以有权限成为主节点和读写磁盘(不写就是默认的)。

cluster.name: my_es1
node.name: node1
network.host: 127.0.0.1
http.port: 9200
transport.tcp.port: 9300
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9302", "127.0.0.1:9303", "127.0.0.1:9304"]

# 2 elasticsearch2节点,集群名称是my_es1,集群端口是9302;节点名称是node2,监听本地9202端口,可以有权限成为主节点和读写磁盘。

cluster.name: my_es1
node.name: node2
network.host: 127.0.0.1
http.port: 9202
transport.tcp.port: 9302
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9302", "127.0.0.1:9303", "127.0.0.1:9304"]

# 3 elasticsearch3节点,集群名称是my_es1,集群端口是9303;节点名称是node3,监听本地9203端口,可以有权限成为主节点和读写磁盘。

cluster.name: my_es1
node.name: node3
network.host: 127.0.0.1
http.port: 9203
transport.tcp.port: 9303
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9302", "127.0.0.1:9303", "127.0.0.1:9304"]

# 4 elasticsearch4节点,集群名称是my_es1,集群端口是9304;节点名称是node4,监听本地9204端口,仅能读写磁盘而不能被选举为主节点。

cluster.name: my_es1
node.name: node4
network.host: 127.0.0.1
http.port: 9204
transport.tcp.port: 9304
node.master: false
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9302", "127.0.0.1:9303", "127.0.0.1:9304"]

由上例的配置可以看到,各节点有一个共同的名字my_es1,但由于是本地环境,所以各节点的名字不能一致,我们分别启动它们,它们通过单播列表相互介绍,发现彼此,然后组成一个my_es1集群。谁是老大则是要看谁先启动了!
View Code

es脑裂问题

1 有多个节点下线,又上线,正常应该加入到集群种,由于网络等各种原因导致几个节点成为了新的集群
2 配置文件种规定,集群节点数必须大于总节点数除以二+1

es打分机制

`TF`是词频(term frequency),而`IDF`是逆文档频率

TF词频:词条在文档中出现的次数
IDF`是逆文档频率 :如果一个词条在索引中的不同文档中出现的次数越多,那么它就越不重要

 

posted @ 2021-06-27 13:34  Οo白麒麟оΟ  阅读(110)  评论(4编辑  收藏  举报