赞
踩
目录
ElasticSearch三:架构原理、工作流程、准实时索引原理、手工控制搜索结果精准度、近似搜索、前缀匹配、短语搜索、权重控制
这里多个文档是指,批量操作多个文档
批量获取文档数据是通过_mget的API来实现的
在URL中不指定index和type
- GET _mget
- {
- "docs": [
- {
- "_index": "es_db",
- "_type": "_doc",
- "_id": 1
- },
- {
- "_index": "es_db",
- "_type": "_doc",
- "_id": 2
- }
- ]
- }
响应结果如下:
- {
- "docs" : [
- {
- "_index" : "es_db",
- "_type" : "_doc",
- "_id" : "1",
- "_version" : 3,
- "_seq_no" : 7,
- "_primary_term" : 1,
- "found" : true,
- "_source" : {
- "name" : "张三666",
- "sex" : 1,
- "age" : 25,
- "address" : "广州天河公园",
- "remark" : "java developer"
- }
- },
- {
- "_index" : "es_db",
- "_type" : "_doc",
- "_id" : "2",
- "_version" : 1,
- "_seq_no" : 1,
- "_primary_term" : 1,
- "found" : true,
- "_source" : {
- "name" : "李四",
- "sex" : 1,
- "age" : 28,
- "address" : "广州荔湾大厦",
- "remark" : "java assistant"
- }
- }
- ]
- }

在URL中指定index
- GET /es_db/_mget
- {
- "docs": [
- {
- "_type":"_doc",
- "_id": 3
- },
- {
- "_type":"_doc",
- "_id": 4
- }
- ]
- }
在URL中指定index和type
- GET /es_db/_doc/_mget
- {
- "docs": [
- {
- "_id": 1
- },
- {
- "_id": 2
- }
- ]
- }
批量对文档进行写操作是通过_bulk的API来实现的
参数类似于:
actionName:表示操作类型,主要有create,index,delete和update
- {"actionName":{"_index":"indexName", "_type":"typeName","_id":"id"}}
- {"field1":"value1", "field2":"value2"}
批量创建文档create
- POST _bulk
- {"create":{"_index":"article", "_type":"_doc", "_id":3}}
- {"id":3,"title":"程序猿1","content":"程序猿666","tags":["java", "面向对象"],"create_time":1554015482530}
- {"create":{"_index":"article", "_type":"_doc", "_id":4}}
- {"id":4,"title":"程序猿2","content":"程序猿NB","tags":["java", "面向对象"],"create_time":1554015482530}
普通创建或全量替换index
如果原文档不存在,则是创建
如果原文档存在,则是替换(全量修改原文档)
- POST _bulk
- {"index":{"_index":"article", "_type":"_doc", "_id":3}}
- {"id":3,"title":"程序猿(一)","content":"程序猿666","tags":["java", "面向对象"],"create_time":1554015482530}
- {"index":{"_index":"article", "_type":"_doc", "_id":4}}
- {"id":4,"title":"程序猿(二)","content":"程序猿NB","tags":["java", "面向对象"],"create_time":1554015482530}
批量删除delete
- POST _bulk
- {"delete":{"_index":"article", "_type":"_doc", "_id":3}}
- {"delete":{"_index":"article", "_type":"_doc", "_id":4}}
批量修改update
- POST _bulk
- {"update":{"_index":"article", "_type":"_doc", "_id":3}}
- {"doc":{"title":"ES大法必修内功"}}
- {"update":{"_index":"article", "_type":"_doc", "_id":4}}
- {"doc":{"create_time":1554018421008}}
Domain Specific Language
领域专用语言
Elasticsearch provides a ful1 Query DSL based on JSON to define queries
Elasticsearch提供了基于JSON的DSL来定义查询。
DSL由叶子查询子句和复合查询子句两种子句组成。
无查询条件是查询所有,默认是查询所有的,或者使用match_all表示所有
- GET /es_db/_doc/_search
- {
- "query":{
- "match_all":{}
- }
- }
叶子条件查询(单字段查询条件)
模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现
match的复杂用法
match条件还支持以下参数:
精确匹配
组合条件查询(多条件查询)
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询条件
must/filter/shoud/must_not 等的子条件是通过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当是多个条件时,对应的是一个数组
连接查询(多文档合并查询)
DSL查询语言中存在两种:查询DSL(query DSL)和过滤DSL(filter DSL)
它们两个的区别如下图:
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
Query方式查询:案例
根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
- POST /es_db/_doc/_search
- {
- "query": {
- "term": {
- "name": "admin"
- }
- }
- }
SQL: select * from student where name = 'admin'
根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
- POST /es_db/_doc/_search
- {
- "from": 0,
- "size": 2,
- "query": {
- "match": {
- "address": "广州"
- }
- }
- }
SQL: select * from user where address like '%广州%' limit 0, 2
多字段模糊匹配查询与精准查询 multi_match
- POST /es_db/_doc/_search
- {
- "query":{
- "multi_match":{
- "query":"张三",
- "fields":["address","name"]
- }
- }
- }
SQL: select * from student where name like '%张三%' or address like '%张三%'
未指定字段条件查询 query_string , 含 AND 与 OR 条件
- POST /es_db/_doc/_search
- {
- "query":{
- "query_string":{
- "query":"广州 OR 长沙"
- }
- }
- }
指定字段条件查询 query_string , 含 AND 与 OR 条件
- POST /es_db/_doc/_search
- {
- "query":{
- "query_string":{
- "query":"admin OR 长沙",
- "fields":["name","address"]
- }
- }
- }
范围查询
注:json请求字符串中部分字段的含义
- POST /es_db/_doc/_search
- {
- "query" : {
- "range" : {
- "age" : {
- "gte":25,
- "lte":28
- }
- }
- }
- }
SQL: select * from user where age between 25 and 28
分页、输出字段、排序综合查询
- POST /es_db/_doc/_search
- {
- "query" : {
- "range" : {
- "age" : {
- "gte":25,
- "lte":28
- }
- }
- },
- "from": 0,
- "size": 2,
- "_source": ["name", "age", "book"],
- "sort": {"age":"desc"}
- }
Filter过滤器方式查询
它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
- POST /es_db/_doc/_search
- {
- "query" : {
- "bool" : {
- "filter" : {
- "term":{
- "age":25
- }
- }
- }
- }
- }
总结:
1. match
match:模糊匹配,需要指定字段名,但是输入会进行分词,比如"hello world"会进行拆分为hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。
2. term
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那么会和match查询结果一样,但是如果查询"hello world",结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有"hello world"的字样,而不是查询字段中包含"hello world"的字样。当保存数据"hello world"时,elasticsearch会对字段内容进行分词,"hello world"会被分成hello和world,不存在"hello world",因此这里的查询结果会为空。这也是term查询和match的区别。
3. match_phase
match_phase:会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以"hello world"为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的,hello that world不满足,world hello也不满足条件。
4. query_string
query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
动态映射:
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
动态映射规则如下:
静态映射:
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
删除原创建的索引
DELETE /es_db
创建索引
PUT /es_db
创建文档(ES根据数据类型, 会自动创建映射)
- PUT /es_db/_doc/1
- {
- "name": "Jack",
- "sex": 1,
- "age": 25,
- "book": "java入门至精通",
- "address": "广州小蛮腰"
- }
获取文档映射
GET /es_db/_mapping
删除原创建的索引
DELETE /es_db
创建索引
PUT /es_db
设置文档映射
"index":true 表示是否建立索引
"store":true 表示是否存储数据,不存储即查询时值为空(有些场景字段不需要查询出值,只做查询条件用,例如:逻辑删除字段,只做为查询条件,不需要返回值则"store":false)
- PUT /es_db
- {
- "mappings":{
- "properties":{
- "name":{"type":"keyword","index":true,"store":true},
- "sex":{"type":"integer","index":true,"store":true},
- "age":{"type":"integer","index":true,"store":true},
- "book":{"type":"text","index":true,"store":true},
- "address":{"type":"text","index":true,"store":true}
- }
- }
- }
根据静态映射创建文档
- PUT /es_db/_doc/1
- {
- "name": "Jack",
- "sex": 1,
- "age": 25,
- "book": "elasticSearch入门至精通",
- "address": "广州车陂"
- }
获取文档映射
GET /es_db/_mapping
将 book 字段设置为 keyword 映射 (只能精准查询, 不能分词查询,能聚合、排序)
- POST /es_db/_doc/_search
- {
- "query": {
- "term": {
- "book": "elasticSearch入门至精通"
- }
- }
- }
将 book 字段设置为 text 映射能模糊查询, 能分词查询,不能聚合、排序)
- POST /es_db/_doc/_search
- {
- "query": {
- "match": {
- "book": "elasticSearch入门至精通"
- }
- }
- }
设置ik分词器的文档映射
- PUT /es_db
- {
- "mappings":{
- "properties":{
- "name":{"type":"keyword","index":true,"store":true},
- "sex":{"type":"integer","index":true,"store":true},
- "age":{"type":"integer","index":true,"store":true},
- "book":{"type":"text","index":true,"store":true,"analyzer":"ik_smart","search_analyzer":"ik_smart"},
- "address":{"type":"text","index":true,"store":true}
- }
- }
- }
分词查询
- POST /es_db/_doc/_search
- {
- "query": {
- "match": {"address": "广"}
- }
- }
-
- POST /es_db/_doc/_search
- {
- "query": {
- "match": {"address": "广州"}
- }
- }
具体方法
如果要推倒现有的映射, 你得重新建立一个静态索引
然后把之前索引里的数据导入到新的索引里
删除原创建的索引
为新索引起个别名, 为原索引名
- POST _reindex
- {
- "source": {
- "index": "db_index"
- },
- "dest": {
- "index": "db_index_2"
- }
- }
-
- DELETE /db_index
-
- PUT /db_index_2/_alias/db_index
注意: 通过这几个步骤就实现了索引的平滑过渡,并且是零停机
在数据库领域中,有两种方法来确保并发更新,不会丢失数据:
悲观并发控制
这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。
乐观并发控制
Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。
再以创建一个文档为例(ES老版本)
- PUT /db_index/_doc/1
- {
- "name": "Jack",
- "sex": 1,
- "age": 25,
- "book": "Spring Boot 入门到精通",
- "remark": "hello world"
- }
实现_version乐观锁更新文档
- PUT /db_index/_doc/1?version=1
- {
- "name": "Jack",
- "sex": 1,
- "age": 25,
- "book": "Spring Boot 入门到精通",
- "remark": "hello world"
- }
ES新版本(7.x)不使用version进行并发版本控制 if_seq_no=版本值&if_primary_term=文档位置
_seq_no:文档版本号,作用同_version
_primary_term:文档所在位置
- POST /es_sc/_search
-
- DELETE /es_sc
-
- POST /es_sc/_doc/1
- {
- "id": 1,
- "name": "程序猿",
- "desc": "优秀的Java程序猿",
- "create_date": "2021-02-24"
- }
-
- POST /es_sc/_update/1
- {
- "doc": {
- "name": "程序猿666"
- }
- }
-
-
- POST /es_sc/_update/1/?if_seq_no=1&if_primary_term=1
- {
- "doc": {
- "name": "程序猿1"
- }
- }
-
- POST /es_sc/_update/1/?if_seq_no=1&if_primary_term=1
- {
- "doc": {
- "name": "程序猿2"
- }
- }

先说集群吧
将安装包分发到其他服务器上面
修改elasticsearch.yml
- mkdir -p /usr/local/es/elasticsearch-7.6.1/log
- mkdir -p /usr/local/es/elasticsearch-7.6.1/data
-
- cd /usr/local/es/elasticsearch-7.6.1/config
-
- rm -rf elasticsearch.yml
-
- vim elasticsearch.yml
- cluster.name: baiqi-es
- node.name: node1.baiqi.cn
- path.data: /usr/local/es/elasticsearch-7.6.1/data
- path.logs: /usr/local/es/elasticsearch-7.6.1/log
- network.host: node1.baiqi.cn
- http.port: 9200
- discovery.seed_hosts: ["IP1", "IP2", "IP3"]
- cluster.initial_master_nodes: ["节点1名称", "节点2名称", "节点3名称"]
- bootstrap.system_call_filter: false
- bootstrap.memory_lock: false
- http.cors.enabled: true
- http.cors.allow-origin: "*"

修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小
- cd /usr/local/es/elasticsearch-7.6.1/config
- vim jvm.options
- -Xms2g
- -Xmx2g
node2与node3修改es配置文件
- mkdir -p /usr/local/es/elasticsearch-7.6.1/log
- mkdir -p /usr/local/es/elasticsearch-7.6.1/data
-
- cd /usr/local/es/elasticsearch-7.6.1/config
-
-
- vim elasticsearch.yml
- cluster.name: baiqi-es
- node.name: node2.baiqi.cn
- path.data: /usr/local/es/elasticsearch-7.6.1/data
- path.logs: /usr/local/es/elasticsearch-7.6.1/log
- network.host: node2.baiqi.cn
- http.port: 9200
- discovery.seed_hosts: ["IP1", "IP2", "IP3"]
- cluster.initial_master_nodes: ["节点1名称", "节点2名称", "节点3名称"]
- bootstrap.system_call_filter: false
- bootstrap.memory_lock: false
- http.cors.enabled: true
- http.cors.allow-origin: "*"

- mkdir -p /usr/local/es/elasticsearch-7.6.1/log
- mkdir -p /usr/local/es/elasticsearch-7.6.1/data
-
- cd /usr/local/es/elasticsearch-7.6.1/config
-
-
- vim elasticsearch.yml
- cluster.name: baiqi-es
- node.name: node3.baiqi.cn
- path.data: /usr/local/es/elasticsearch-7.6.1/data
- path.logs: /usr/local/es/elasticsearch-7.6.1/log
- network.host: node3.baiqi.cn
- http.port: 9200
- discovery.seed_hosts: ["IP1", "IP2", "IP3"]
- cluster.initial_master_nodes: ["节点1名称", "节点2名称", "节点3名称"]
- bootstrap.system_call_filter: false
- bootstrap.memory_lock: false
- http.cors.enabled: true
- http.cors.allow-origin: "*"

查看集群状态:
- GET _cat/nodes?v
- GET _cat/health?v
由于es服务启动之后,访问界面比较丑陋,为了更好的查看索引库当中的信息,我们可以通过安装elasticsearch-head这个插件来实现,这个插件可以更方便快捷的看到es的管理界面
elasticsearch-head这个插件是es提供的一个用于图形化界面查看的一个插件工具,可以安装上这个插件之后,通过这个插件来实现我们通过浏览器查看es当中的数据
安装elasticsearch-head这个插件这里提供两种方式进行安装,第一种方式就是自己下载源码包进行编译,耗时比较长,网络较差的情况下,基本上不可能安装成功。
第二种方式就是直接使用我已经编译好的安装包,进行修改配置即可
要安装elasticsearch-head插件,需要先安装Node.js
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 不是一个 JavaScript 框架,不同于CakePHP、Django、Rails。Node.js 更不是浏览器端的库,不能与 jQuery、ExtJS 相提并论。Node.js 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。
下载安装包
node1机器执行以下命令下载安装包,然后进行解压
- cd /usr/local/es
- wget https://npm.taobao.org/mirrors/node/v8.1.0/node-v8.1.0-linux-x64.tar.gz
- tar -zxvf node-v8.1.0-linux-x64.tar.gz -C /usr/local/es/
创建软连接
- sudo ln -s /usr/local/es/node-v8.1.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
- sudo ln -s /usr/local/es/node-v8.1.0-linux-x64/bin/node /usr/local/bin/node
修改环境变量
- vi /etc/profile
- export NODE_HOME=/usr/local/es/node-v8.1.0-linux-x64
- export PATH=:$PATH:$NODE_HOME/bin
修改完环境变量使用source生效
source /etc/profile
验证安装成功
- node -v
- npm -v
上传压缩包到/usr/local/es路径下去
将我们的压缩包 elasticsearch-head-compile-after.tar.gz 上传到服务器的/usr/local/es 路径下面去
解压安装包
- cd /usr/local/es/
- tar -zxvf elasticsearch-head-compile-after.tar.gz -C /usr/local/es/
修改Gruntfile.js
- cd /usr/local/es/elasticsearch-head
- vim Gruntfile.js
找到代码中的93行:hostname: '192.168.100.100', 修改为:节点地址
- connect: {
- server: {
- options: {
- hostname: '节点地址',
- port: 9100,
- base: '.',
- keepalive: true
- }
- }
- }
机器修改app.js
- cd /usr/local/es/elasticsearch-head/_site
- vim app.js
在Vim中输入「:4354」,定位到第4354行,修改 http://localhost:9200为http://节点地址:9200
启动head服务
启动elasticsearch-head插件
cd /usr/local/es/elasticsearch-head/node_modules/grunt/bin/
进程前台启动命令
./grunt server
进程后台启动命令
nohup ./grunt server >/dev/null 2>&1 &
- Running "connect:server" (connect) taskWaiting forever...Started connect web server on http://192.168.52.100:9100
- 如何停止:elasticsearch-head进程
- 执行以下命令找到elasticsearch-head的插件进程,然后使用kill -9 杀死进程即可
- netstat -nltp | grep 9100
- kill -9 8328
访问elasticsearch-head界面
打开Google Chrome访问
注意:搭建es集群,启动三个es节点,访问elasticsearch-head时只显示一个master
解决方案:进到节点2、3的/elasticsearch-7.6.1/data/目录下删除nodes文件,之后重启节点2、3的es进程即可
https://blog.csdn.net/Xx__WangQi/article/details/114907064
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。