ElasticSearch7-3-0的客户端操作

x33g5p2x  于2021-10-17 转载在 ElasticSearch  
字(11.4k)|赞(0)|评价(0)|浏览(1008)

其他教程

https://blog.csdn.net/weixin_43495317/article/details/104507018 基础语法

https://blog.csdn.net/qq_26502245/article/details/95607656 7x 常规操作

https://blog.csdn.net/weixin_42681513/article/details/105632063 常用搜索

https://www.elastic.co/guide/en/elasticsearch/reference/7.3/index.html 官方文档

7.x的改变

含义

  • Index:索引
  • Type:类型。
  • Document:文档。

文档是 JSON 类型的。

与 MySQL 类比

可以将 ES 中的这三个概念和 MySQL 类比:

  • Index 对应 MySQL 中的 Database(数据库);
  • Type 对应 MySQL 中的 Table; (7取消了)
  • Document 对应 MySQL 中表的记录。

一个MySQL实例中可以创建多个 Database,一个Database中可以创建多个Table。

现在ES7的概念

  • Index 对应 MySQL 中的 table(表);
  • Document 对应 MySQL 中表的记录。

从 ES 7.0 开始,Type 被废弃(只能一个)

在 7.0 以及之后的版本中 Type 被废弃了。一个 index 中只有一个默认的 type,即 _doc。(ES8以后直接取消)

ES 的Type 被废弃后,库表合一,Index 既可以被认为对应 MySQL 的 Database,也可以认为对应 table。

也可以这样理解:

  • ES整体 对应 MySQL的一个 Database。
  • Index 对应 MySQL 中的 Table 。
  • Document 对应 MySQL 中表的记录。

为什么映射类型被移除

一开始,我们把索引比作是关系型数据库中的数据库,映射type比作了表。其实这个比喻是错误的,在关系型数据库中表是相互独立的,不同表中相同的列是没有关联关系的,这个与映射type是不一样的。
在es的索引中,不同的映射类型中存在相同的属性名,他们底层都是使用同一个Lucene属性。比如上面的商品例子中,电器和生鲜都有name字段,他们必须要有相同的映射类型才可以。例如在同一个索引中,deleted属性你在A类型中想用date来表示,在B类型中想用boolean来表示,像这种情况就不支持了。
最重要的是同一个索引中共同字段比较少或者没有,那么会导致数据太稀疏,这会影响Lucene有效压缩文档的能力,导致你的搜索很慢。
就是因为这些原因,es官方决定删除映射type这个概念。

替换方案一个文档一个索引

把之前的电器类型和生鲜类型分别建立电器索引和生鲜索引

因为索引是相互独立的,不存在相同字段的冲突问题。使用这种方式有2个好处:
1、数据更加密集,有利于Lucene的压缩。
2、做统计的时候数据会更加准确,因为数据都在同一个索引中。
每个索引都可以根据自己实际需要存储多大的数据来进行调整,你可以对不同的索引设置不同的分片和副本。

使用Postman工具进行Restful接口访问

使用前必须保证 elasticsearch 和 elasticsearch-head 启动 而且健康值 为绿色或者黄色 不能是灰色

ElasticSearch的接口语法

curl ‐X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' ‐d '<BODY>

参数解析:

ES Restful API GET、POST、PUT、DELETE、HEAD含义:
1)GET:获取请求对象的当前状态。
2)POST:改变对象的当前状态。
3)PUT:创建一个对象。
4)DELETE:销毁对象。
5)HEAD:请求获取对象的基础信息。

发送Body数据前 一定要先用 https://www.json.cn//# 这个网站里的json 检测一下 看看格式是否正确 否则会报错400

ES中数据类型

查看 ElasticSearch常用字段类型这篇文章

ES7x基础语法教程

查看ES状态

GET http://192.168.81.141:9200/_cat/health

红色表示数据不可用,黄色表示数据可用,部分副本没有分配,绿色表示一切正常

查询ES全部存在的索引

GET http://192.168.81.141:9200/_cat/indices?v

添加索引

语法:

PUT http://192.168.81.141:9200/要添加的索引名称

列:

PUT http://192.168.81.141:9200/index1

索引=表 (properties下面内容就是表示这个表的每个字段是干嘛的)

给索引添加字段信息

我们在es中添加索引数据时,可以不需要指定数据类型,es中有自动影射机制,字符串映射为string,数字映射为long。

字符串类型的自动影射机制,默认情况

"name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                }

ignore_above忽略长度超过256字符串。 用于设置超过指定字符后,超出的部分不能被索引或者存储

其他基本数据类型的自动影射机制,默认情况

"price": {
                    "type": "float"
                }

我们可以自己通过mappings可以指定数据类型是否存储等属性。

比如: 如果想给指定字段用指定的分词器那么,就需要手动添加,

语法:

PUT http://192.168.81.141:9200/指定索引/_mappings

列:

PUT http://192.168.81.141:9200/index1/_mappings

{
 "properties": {
            "name": {
                "type": "text",
                "analyzer": "ik_max_word"
            },
            "age": {
                "type": "long",
                "index": false
            },
            "like": {
                "type": "text",
                "analyzer": "ik_max_word"
            },
            "desc": {
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
}

index为false时es不会为该属性创建索引(本质是不做分词),也就是说不能当做主查询条件 (默认为true)

单独添加一个字段类型

在ES7中可以不用一次性把全部字段的映射信息都创建好, 可以根据后来根据业务情况自行进行补充

因为: 现在一个索引下面的数据全部都通用一个类型(_doc)

比如: 我现在index1索引映射的类型是:

{
    "index1": {
        "mappings": {
            "properties": {
                "name": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "age": {
                    "type": "long",
                    "index": false
                },
                "like": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "desc": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                }
            }
        }
    }
}

插入时候数据是

{
     "name":"胡",
     "age":"22",
     "like":"你好世界",
     "desc":"ES初学者"
}

那么现在需求来了, 添加一个时间字段,用于查询指定时间段的数据

第一步先添加映射字段

{
 "properties": {
            "time": {
                "type": "date",
                "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis||date_optional_time ",
                "index": true
            }
        }
}

会有三种情况发生:

如果原来存在那么判断类型是否一致如果都一样那么, 执行成功
1.
如果原来不存在,就在原来的映射里添加这个字段映射信息, 执行成功
1.
如果原来字段存在,并且原来字段内数据的类型和要修改的不一样,那么就会报错

mapper [time] of different type, current_type [text], merged_type [date]

为了避免第3点的问题发送,我们在映射字段前去,查询下当前索引的映射情况,不要和原来的字段名称一样了

GET http://192.168.81.141:9200/index1/_mappings 查询索引内映射的情况

插入的时候数据是

{
     "name":"胡",
     "age":"22",
     "like":"你好世界",
     "desc":"ES初学者",
     "time": "2021-2-11"
}

创建索引的同时添加字段信息

语法: PUT http://192.168.81.141:9200/要添加的索引名称

列:

PUT http://192.168.81.141:9200/index1

{
  "mappings": {
    "properties": {
      "name": {
        "type":"text",
         "analyzer": "ik_max_word",
          "index": true
      },
      "age": {
         "type": "long",
         "index": false
      },
      "like":{
        "type":"text",
        "analyzer": "ik_max_word",
        "index": true
      },
      "desc":{
        "type":"text",
         "analyzer": "ik_max_word",
         "index": true
      }
    }
  }
}

注意: 只要是需要查询的字符串类型的一定要使用

  1. “type”:“text”
  2. “analyzer”: “ik_max_word”
  3. “index”: true

其他不参与索引的配置

  1. “type”: “long”
  2. “index”: false

修改索引映射…各种信息

elasticsearch 并不支持修改mapping映射字段,无法直接修改,所以需要曲线救国。

原来的索引 index1, 新索引index2

先创建一个新索引,然后添加玩映射信息

PUT http://192.168.81.142:9200/index2
1.
将原来索引数据迁移到新索引中

POST http://192.168.81.142:9200/_reindex?slices=auto&refresh

{
  "source": {
    "index": "index1",
    "size": 5000
  },
  "dest": {
    "index": "index2",
    "version_type": "internal"
  }
}

source->index(原来的索引名称)

dest->index(新索引名称)

其他的配置不用动
1.
删除原来的索引

DELETE http://192.168.81.142:9200/index1
1.
给新索引添加别名 ,别名的名称是原来索引的名称,这样就不会影响到程序

POSThttp://192.168.81.142:9200/_aliases

{
  "actions" : [
    { "add" : { "index" : "index2", "alias" : "index1" } }
  ]
}

index 需要添加别名的索引名称, alias 起别名

查询指定索引的详情

语法:

GET http://192.168.81.141:9200/索引名称/_mappings

列:

GET http://192.168.81.141:9200/index1/_mappings

结果显示:

{
    "index1": {
        "mappings": {
            "properties": {
                "age": {
                    "type": "long",
                    "index": false
                },
                "desc": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "like": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "name": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                }
            }
        }
    }
}

删除指定索引

语法:

DELETE http://127.0.0.1:9200/索引名称

列:

DELETE http://192.168.81.141:9200/index1

查询指定索引下全部数据

语法:

GET http://192.168.81.141:9200/索引名称/_search

列:

GET http://192.168.81.141:9200/index1/_search

结果

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    }
}

我这是索引中没有数据,你可以自己添加几天试试

清空索引下全部数据

POST http://192.168.81.141:9200/index1/_delete_by_query

Body

{
  "query": {
    "match_all": {}
  }
}

返回:

{
    "took": 71,
    "timed_out": false,
    "total": 5,
    "deleted": 5,
    "batches": 1,
    "version_conflicts": 0,
    "noops": 0,
    "retries": {
        "bulk": 0,
        "search": 0
    },
    "throttled_millis": 0,
    "requests_per_second": -1.0,
    "throttled_until_millis": 0,
    "failures": []
}

文档基本操作

创建文档document(一条数据)

文档等同于数据库的1行, 在es7x必须通过{index}/_doc 来自动创建id,通过{index}/_doc/{id}指定文档的id

语法:

POST http://192.168.81.141:9200/index1/_doc/文档的id

列:

POST http://192.168.81.141:9200/index1/_doc/1

Body(添加的内容)

{
    "name":"胡",
    "age":"22",
     "like":"你好世界",
     "desc":"ES初学者"
}

结果显示:

{
    "_index": "index1",
    "_type": "_doc",
    "_id": "1",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 2,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}
查询指定索引下的指定文档(一条数据)

语法: GET http://192.168.81.141:9200/index1/_doc/文档id

列:

GET http://192.168.81.141:9200/index1/_doc/1

结果:

{
    "_index": "index1",
    "_type": "_doc",
    "_id": "1",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "胡",
        "age": "22",
        "like": "你好世界",
        "desc": "ES初学者"
    }
}
修改指定索引下文档(一条数据)

修改文档其实 就和创建文档一样 (覆盖就行)

语法: POST http://192.168.81.141:9200/index1/_doc/文档id

列:

POST http://192.168.81.141:9200/index1/_doc/文档id

Body

{
    "name":"胡1",
    "age":"23",
     "like":"你好世界1",
     "desc":"ES初学者1"
}

结果显示:

{
    "_index": "index1",
    "_type": "_doc",
    "_id": "1",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 2,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}
删除指定索引下的指定文档(一条数据)

语法: DELETE http://192.168.81.141:9200/index1/_doc/文档id

列:

DELETE http://192.168.81.141:9200/index1/_doc/1

结果:

{
    "_index": "index1",
    "_type": "_doc",
    "_id": "1",
    "_version": 3,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 2,
        "failed": 0
    },
    "_seq_no": 2,
    "_primary_term": 1
}

文档高级查询

查询文档query_string查询

以分词进行 匹配查询 ,用于文档匹配 ,标题匹配 … 等

运算符

“default_operator”:“运算符”

有AND、OR,默认为OR。

比如query里面的内容是 ”搜索服务器”,那么只要分词集中 包含之一就可以匹配。

如果"default_operator":“AND”, 那么就是全匹配

比如: query里面的内容是 ”搜索服务器”

那么只要分词集内词 能拼出 ”搜索服务器” 这整句话 就可以匹配

通配符

支持一些简单的wildcard写法。比如fields:[“nam/*”]即任何nam开头的字段

/* , 可以代替一个任意字符、/*可代表任意个字符(包括零个)

比如你要查询的内容很长,记不清了但是你记得末尾是tor,那么你只需要把query内容写成/*tor即可

正则

如果要在query的内容中使用正则表达式,在两端加上正斜杠/即可。比如: name:/ob[am]{2}a/ 可以到网上查 具体怎么写

需要 发送POST请求 无须文档id 需要在 表 后面追加 /_search

POST http://192.168.81.141:9200/index1/_search

Body内容

{
    "query":{
        "query_string":{
            "default_field":"like",
            "query":"你好"
        }
    }
}

可以发现是能查询到结果的因为 query_string 默认采用的 or 匹配 以及standard分词器

default_field: 查询的字段 默认为_all 即对所有字段进行查询
*
query: 需要查询的具体内容 (如果不指定file那么就是查询所有字段的所有内容)

{
    "query":{
        "query_string":{
            "query":"2021"
        }
    }
}

field与query写在一起比如”query”:”title:搜索服务器”时候 default_field就没必要了

{
    "query":{
        "query_string":{
            "query":"like:你好"
        }
    }
}

注意: 如果需要要使用到wildcard的话 "query":"like:/*界"

query_string 支持多字段 "fields" : ["age", "name"], 可以把default_field去掉使用fields,

{
    "query":{
        "query_string":{
          "fields" : ["name", "like"],
           "query":"胡"
        }
    }
}
查询文档term查询

Term查询会采用精确匹配。

通常用于数字,日期和枚举等结构化数据,

term是代表完全匹配,也就是精确查询,搜索词必须是分词集合中的一个

发送POST请求 http://192.168.81.141:9200/index1/_search

Body

{
    "query":{
        "term":{
            "like":"你好"
        }
    }
}
查询文档Match查询

match模糊匹配,需要指定字段名,但是输入会进行分词,比如"hello world"会进行拆分为hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。

{ 
  "query": {
    "match": {
        "like": "世界"
      }
  }
}
查询文档match_phase查询

match_phase(近似匹配):会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以"hello world"为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的,hello that word不满足,world hello也不满足条件。

POST http://192.168.81.141:9200/index1/_search

{
  "query": {
    "match_phrase": {
      "like": "世界"
    }
  }
}

还有很多更高级的语法这里就不继续了,自行看上面提供的教程网站,或者自行百度就行了,毕竟我们重点是在java中操作

相关文章