GVKun编程网logo

第14篇:一文读懂Elasticsearch强大的排序能力(elasticsearch排序原理)

26

如果您想了解第14篇:一文读懂Elasticsearch强大的排序能力和elasticsearch排序原理的知识,那么本篇文章将是您的不二之选。我们将深入剖析第14篇:一文读懂Elasticsearc

如果您想了解第14篇:一文读懂Elasticsearch强大的排序能力elasticsearch排序原理的知识,那么本篇文章将是您的不二之选。我们将深入剖析第14篇:一文读懂Elasticsearch强大的排序能力的各个方面,并为您解答elasticsearch排序原理的疑在这篇文章中,我们将为您介绍第14篇:一文读懂Elasticsearch强大的排序能力的相关知识,同时也会详细的解释elasticsearch排序原理的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

第14篇:一文读懂Elasticsearch强大的排序能力(elasticsearch排序原理)

第14篇:一文读懂Elasticsearch强大的排序能力(elasticsearch排序原理)

背景:目前国内有大量的公司都在使用 Elasticsearch,包括阿里、京东、滴滴、今日头条、小米、vivo等诸多知名公司。除了搜索功能之外,Elasticsearch还结合Kibana、Logstash、Elastic Stack还被广泛运用在大数据近实时分析领域,包括日志分析、指标监控等多个领域。 

本节内容:Elasticsearch的排序原理。

目录

1、默认按照_score排序

2、按照单字段排序

3、按照多字段排序

4、单字段多值排序

5、字符串排序与多字段


我们知道,Elasticsearch默认情况下,返回的结果是按照相关性_score进行排序的,即最相关的文档排在最前。 在日常业务当中,Elasticsearch排序会被经常使用,今天我带着大家看看Elasticsearch sort参数含义以及如何使用sort进行排序。

1、默认按照_score排序

为了按照相关性来排序,需要将相关性_score表示为一个数值。在 Elasticsearch 中, 相关性得分由一个浮点数进行表示,并在搜索结果中通过 _score参数返回, 默认排序是按照_score降序。

http://localhost:9201/student/_search

查询请求,比如需要查询id为1的数据。 

{
    "query" : {
        "bool" : {
            "filter" : {
                "term" : {
                    "id" : 1
                }
            }
        }
    }
}

查询结果如下,

{
    "took": 3,"timed_out": false,"_shards": {
        "total": 1,"successful": 1,"skipped": 0,"Failed": 0
    },"hits": {
        "total": {
            "value": 1,"relation": "eq"
        },"max_score": 0,"hits": [
            {
                "_index": "student","_type": "_doc","_id": "1","_score": 0,// 相关性评分,无意义的值
                "_source": {
                    "love": "I like to collect rock albums","createTime": "2022-05-28 14:19:05","name": "test1","id": "1","age": 1
                }
            }
        ]
    }
}

上面的相关性评分可能对于生产环境而言并没有实际业务意义。因为当使用 filter过滤时,这表明只是希望获取匹配 id为1的文档数据,而并没有试图确定这些文档的相关性。 如果有多个文档,此时文档会按照随机顺序返回,并且每个文档都会评为零分。

如果我们想把这个没有意义的分数过滤掉。可以使用 constant_score 关键字对查询条件进行替换:

{
    "query" : {
        "constant_score" : { //constant_score替换前面的bool
            "filter" : {
                "term" : {
                    "id" : 1
                }
            }
        }
    }
}

最终查询结果如下,

{
    "took": 5,"max_score": 1,"_score": 1,//恒定分值,默认为1
                "_source": {
                    "love": "I like to collect rock albums","age": 1
                }
            }
        ]
    }
}

此时执行与前面相同的查询请求,返回的所有文档_score的恒定值为1。

2、按照单字段排序

在实际业务场景中,通常会根据具体的单个业务字段进行排序,比如 数值、日期等。

请求参数,比如我们需要查询按照创建倒序进行对学习排序,此时可以使用sort参数进行实现。

{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "id": 1
        }
      }
    }
  },"sort": {
    "createTime": {
      "order": "desc"
    }
  }
}

响应参数如下, 

{
    "took": 2,"max_score": null,//返回为空
        "hits": [
            {
                "_index": "student","_score": null,//返回为空
                "_source": {
                    "love": "I like to collect rock albums","age": 1
                },"sort": [ // 新的节点
                    1653747545000 //排序字段值
                ]
            }
        ]
    }
}

此时,我们发现_score的值为null,此时表示_score没有用于排序。

createTime 字段的值表示为自 epoch (January 1,1970 00:00:00 UTC)以来的毫秒数,通过 sort 字段的值进行返回。

每个返回结果中会有一个新的节点sort元素,它包含了用于排序的值。 在这个案例中,我们按照 createTime 进行排序,在内部被索引为自epoch以来的毫秒数。 long 类型数1653747545000等价于日期字符串2022-5-28 22:19:50UTC 。

其次 _score 和 max_score 字段都是 null 。计算 _score对性能会有比较大的损耗,通常仅用于排序; 我们一般情况下,并不会根据相关性排序,所以记录_score是没有意义的。如果你的需要场景确实需要计算_score, 此时可以将在请求参数中加track_scores参数,并设置值为true 。

{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "id": 1
        }
      }
    }
  },"track_scores": true,// 将track_scores设置为true
  "sort": {
    "createTime": {
      "order": "desc"
    }
  }
}

字段将会默认升序排序,而按照 _score 的值进行降序排序。

3、按照多字段排序

假定我们想要结合使用 createTime 和_score 进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序。

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "love": "I like to collect rock albums"
        }
      },"filter": {
        "term": {
          "id": 1
        }
      }
    }
  },"sort": [
    {
      "createTime": {
        "order": "desc"
      }
    },{
      "_score": {
        "order": "desc"
      }
    }
  ]
}

排序条件的顺序是很重要的。结果首先按第一个条件排序,仅当结果集的第一个 sort 值完全相同时才会按照第二个条件进行排序,以此类推。

多级排序并不一定包含_score字段。你也可以根据实际业务场景,针对一些不同的字段联合进行排序。

4、单字段多值排序

这种场景是单个字段需要根据多个值进行排序,而且这些值并没有固有的顺序;一个字段多值进行排序,这时应该选择哪个进行排序呢?

如果是数字或日期,你可以将多值字段减为单值,这可以通过使用 min 、 max 、 avg 或是 sum 排序模式 。

比如,你可以按照每个 createTime 字段中的最早日期进行排序,通过以下方法:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "love": "I like to collect rock albums"
        }
      },"sort": {
    "createTime": {
      "order": "asc","mode": "min"
    }
  }
}

  返回结果,

{
    "took": 10,"_source": {
                    "love": "I like to collect rock albums","sort": [
                    1653747545000
                ]
            }
        ]
    }
}

此种应用场景实际生产环境中使用比较少,具体使用需要结合自身业务需求而定。

5、字符串排序与多字段

有一些业务场景下,我们需要根据某个字段的字符串值进行排序。这在普通的关系型数据库中是很难实现的,那在Elasticsearch是怎么处理的呢?

为了对字符串字段进行排序,这个字段在创建索引时,需包含一项:index为not_analyzed。 但是我们仍需要 analyzed 字段,这样才能以全文进行查询。

通常有一个简单的方法解决这个问题:就是用两个字段存储同一个字符串,一个设置为analyzed 用于搜索, 另一个设置为not_analyzed用于排序。

但是如果重复保存相同的字符串两次,在_source字段是浪费空间的。 我们所希望的是传递一个单字段但是却用两种方式索引它。所有的 _core_field 类型 (strings,numbers,Booleans,dates) 接收一个 fields 参数。

此时,在建立映射是,可设置如下:

// < 7.x版本
"love": { 
    "type":     "string","fields": {
        "raw": { //子字段
            "type":  "string","index": "not_analyzed" //设置为not_analyzed 
        }
    }
}

// >= 7.x 版本
"love": {
    "type":     "keyword","fields": {
        "raw": {
        "type":  "keyword"
        }
    }
}  

love 字段与之前的一样: 是一个analyzed全文字段。而新增加的 love.raw 子字段是 not_analyzed.

现在,至少只要我们重新索引了我们的数据,使用 love 字段用于搜索,love.raw 字段用于排序。

请求样例如下,

{
  "sort": "love.raw"
}

如果没建该字段,则会提示如下信息:

{
    "error": {
        "root_cause": [
            {
                "type": "query_shard_exception","reason": "No mapping found for [love.raw] in order to sort on","index_uuid": "PJE50ZroS4OiTMObGhkw7Q","index": "student"
            }
        ],"type": "search_phase_execution_exception","reason": "all shards Failed","phase": "query","grouped": true,"Failed_shards": [
            {
                "shard": 0,"index": "student","node": "ufFZIzzWQkaNgoJXsUn3Sg","reason": {
                    "type": "query_shard_exception","index": "student"
                }
            }
        ]
    },"status": 400
}

此时需要重建索引信息如下,

{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },"age": {
        "type": "integer"
      },"love": {
        "type":     "keyword","fields": {
          "raw": {
            "type":  "keyword"
          }
        }
      },"createTime": {
        "format": "yyyy-MM-dd HH:mm:ss","type": "date"
      }
    }
  }
}

最终查询结果如下,

{
    "took": 6,"hits": {
        "total": {
            "value": 20,"createTime": "2022-06-03 17:37:16","name": "test9","sort": [
                    "I like to collect rock albums"
                ]
            },{
                "_index": "student","_id": "3","createTime": "2022-06-03 17:37:17","id": "3","age": 3
                },"_id": "5","id": "5","age": 5
                },"_id": "7","createTime": "2022-06-03 17:37:18","id": "7","age": 7
                },"_id": "9","id": "9","age": 9
                },"_id": "11","createTime": "2022-06-03 17:37:19","id": "11","age": 11
                },"_id": "13","id": "13","age": 13
                },"_id": "15","id": "15","age": 15
                },"_id": "17","createTime": "2022-06-03 17:37:20","id": "17","age": 17
                },"_id": "19","id": "19","age": 19
                },"sort": [
                    "I like to collect rock albums"
                ]
            }
        ]
    }
}

docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器

docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器

0.  docker pull 拉取 elasticsearch + elasticsearch-head 镜像


 

1.  启动 elasticsearch Docker 镜像

docker run -di --name tensquare_elasticsearch -p 9200:9200 -p 9300:9300 elasticsearch

对应 IP:9200 ---- 反馈下边 json 数据,表示启动成功


 

2.  启动 elasticsearch-head 镜像

docker run -d -p 9100:9100 elasticsearch-head

 

对应 IP:9100 ---- 得到下边页面,即启动成功

 


 

3.  解决跨域问题

 

   进入 elasticsearch-head 页面,出现灰色未连接状态 , 即出现跨域问题

 

     1. 根据 docker ps 得到 elasticsearch 的 CONTAINER ID

   2. docker exec -it elasticsearch 的 CONTAINER ID  /bin/bash 进入容器内

     3. cd ./config 

     4. 修改 elasticsearch.yml 文件

echo "
http.cors.enabled: true
http.cors.allow-origin: ''*''" >> elasticsearch.yml

 


 

4.  重启 elasticsearch

docker restart elasticsearch的CONTAINER ID

重新进入 IP:9100 进入 elasticsearch-head, 出现绿色标注,配置成功 !

 

 


 

5.  ik 分词器的安装

  将在 ik 所在的文件夹下,拷贝到 /usr/share/elasticsearch/plugins  ---  注意: elasticsearch 的版本号必须与 ik 分词器的版本号一致

docker cp ik elasticsearch的CONTAINER ID:/usr/share/elasticsearch/plugins
重启elasticsearch
docker restart elasticsearch

未添加ik分词器:http://IP:9200/_analyze?analyzer=chinese&pretty=true&text=我爱中国
添加ik分词器后:http://IP:9200/_analyze?analyzer=ik_smart&pretty=true&text=我爱中国

Docker部署ElasticSearch和ElasticSearch-Head

Docker部署ElasticSearch和ElasticSearch-Head

Docker部署ElasticSearch和ElasticSearch-Head

 本篇主要讲解使用Docker如何部署ElasticSearch:6.8.4 版本,讲解了从Docker拉取到最终运行ElasticSearch 以及 安装 ElasticSearch-Head 用来管理ElasticSearch相关信息的一个小工具,本博客系统首页的搜索正是使用了ElasticSearch来实现的,由于ElasticSearch 更新太快 以至于SpringData-ElasticSearch都跟不上 Es的更新 我也是一开始下载8.x的版本 导致SpringData-ElasticSearch 报错 最终我选择了6.8.4 在此记录一下

 1.Docker部署ElasticSearch:6.8.4版本

  1.1 拉取镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.8.4
  1.2 运行容器

  ElasticSearch的默认端口是9200,我们把宿主环境9200端口映射到Docker容器中的9200端口,就可以访问到Docker容器中的ElasticSearch服务了,同时我们把这个容器命名为es。

docker run -d --name es -p 9200:9200 -p 9300:9300 
-e "discovery.type=single-node" 
-e ES_JAVA_OPTS="-Xms=256m -Xms=256m" 
docker.elastic.co/elasticsearch/elasticsearch:6.8.4

  说明:
  -e discovery.type=single-node :表示单节点启动
  -e ES_JAVA_OPTS="-Xms=256m -Xms=256m" :表示设置es启动的内存大小,这个真的要设置,不然后时候会内存不够,比如我自己的辣鸡服务器!

  1.3 内存不足问题

  centos下载完elasticsearch并修改完配置后运行docker命令:

  发现没有启动成功,去除命令的-d后打印错误如下

Java HotSpot(TM) 64-Bit Server VM warning: INFO:
os::commit_memory(0x0000000085330000, 2060255232, 0) failed;
error=’Cannot allocate memory’ (errno=12)

  经过一番查找发现这是由于elasticsearch6.0默认分配jvm空间大小为2g,内存不足以分配导致。

  解决方法就是修改jvm空间分配
  运行命令:

find /var/lib/docker/overlay/ -name jvm.options


查找jvm.options文件,找到后进入使用vi命令打开jvm.options如下:

将

-Xms2g  
-Xmx2g
修改为
-Xms512m  
-Xmx512m 

  保存退出即可。再次运行创建运行elasticsearch命令,成功启动。

 2.Docker部署ElasticSearch-Heard

  2.1 拉取镜像
docker pull  mobz/elasticsearch-head:5
  2.2 运行容器
docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
  2.3 启动容器
docker start elasticsearch-head
  2.4 打开浏览器: http://IP:9100

  发现连接不上,是因为有跨域问题,因为前后端分离开发的所以需要设置一下es

  2.5 进入刚刚启动的 es 容器,容器name = es
docker exec -it es /bin/bash
  2.6 修改elasticsearch.yml文件
vi config/elasticsearch.yml

添加
http.cors.enabled: true
http.cors.allow-origin: "*"

  其实就是SpringBoot的yml文件 添加跨域支持

  2.7 退出容器 并重启
exit
docker restart es
  2.8 访问http://localhost:9100

es.png

 总结:

  本篇只是简单的讲解了如何用Docker安装ElasticSearch 并且会遇到的坑,包括内存不足,或者版本太高等问题,以及ElasticSearch-Heard的安装和跨域的配置 ,下一篇将讲解ElasticSearch如何安装中文分词器

个人博客网站 https://www.askajohnny.com 欢迎来访问!
本文由博客一文多发平台 OpenWrite 发布!

Docker部署ElasticSearch和ElasticSearch-Head的实现

Docker部署ElasticSearch和ElasticSearch-Head的实现

本篇主要讲解使用Docker如何部署ElasticSearch:6.8.4 版本,讲解了从Docker拉取到最终运行ElasticSearch 以及 安装 ElasticSearch-Head 用来管理ElasticSearch相关信息的一个小工具,本博客系统首页的搜索正是使用了ElasticSearch来实现的,由于ElasticSearch 更新太快 以至于SpringData-ElasticSearch都跟不上 Es的更新 我也是一开始下载8.x的版本 导致SpringData-ElasticSearch 报错 最终我选择了6.8.4 在此记录一下

1.Docker部署ElasticSearch:6.8.4版本

1.1 拉取镜像

docker pull docker.elastic.co/elasticsearch/elasticsearch:6.8.4

1.2 运行容器

ElasticSearch的默认端口是9200,我们把宿主环境9200端口映射到Docker容器中的9200端口,就可以访问到Docker容器中的ElasticSearch服务了,同时我们把这个容器命名为es。

docker run -d --name es -p 9200:9200 -p 9300:9300 
-e "discovery.type=single-node" 
-e ES_JAVA_OPTS="-Xms=256m -Xms=256m" 
docker.elastic.co/elasticsearch/elasticsearch:6.8.4

说明:

-e discovery.type=single-node :表示单节点启动

-e ES_JAVA_OPTS="-Xms=256m -Xms=256m" :表示设置es启动的内存大小,这个真的要设置,不然后时候会内存不够,比如我自己的辣鸡服务器!

1.3 内存不足问题

centos下载完elasticsearch并修改完配置后运行docker命令:

发现没有启动成功,去除命令的-d后打印错误如下

Java HotSpot(TM) 64-Bit Server VM warning: INFO:
os::commit_memory(0x0000000085330000, 2060255232, 0) failed;
error=''Cannot allocate memory'' (errno=12)

经过一番查找发现这是由于elasticsearch6.0默认分配jvm空间大小为2g,内存不足以分配导致。

解决方法就是修改jvm空间分配
运行命令:

find /var/lib/docker/overlay/ -name jvm.options

查找jvm.options文件,找到后进入使用vi命令打开jvm.options如下:

将

-Xms2g 
-Xmx2g
修改为
-Xms512m 
-Xmx512m 

保存退出即可。再次运行创建运行elasticsearch命令,成功启动。

2.Docker部署ElasticSearch-Heard

2.1 拉取镜像

docker pull mobz/elasticsearch-head:5

2.2 运行容器

docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5

2.3 启动容器

docker start elasticsearch-head

2.4 打开浏览器: http://IP:9100

发现连接不上,是因为有跨域问题,因为前后端分离开发的所以需要设置一下es

2.5 进入刚刚启动的 es 容器,容器name = es

docker exec -it es /bin/bash

2.6 修改elasticsearch.yml文件

vi config/elasticsearch.yml

添加

http.cors.enabled: true
http.cors.allow-origin: "*"

其实就是SpringBoot的yml文件 添加跨域支持

2.7 退出容器 并重启

exit
docker restart es

2.8 访问http://localhost:9100

总结:

本篇只是简单的讲解了如何用Docker安装ElasticSearch 并且会遇到的坑,包括内存不足,或者版本太高等问题,以及ElasticSearch-Heard的安装和跨域的配置 ,下一篇将讲解ElasticSearch如何安装中文分词器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • Docker安装ElasticSearch和Kibana的问题及处理方法
  • docker安装Elasticsearch7.6集群并设置密码的方法步骤
  • 一文搞定Docker安装ElasticSearch的过程
  • 在Docker中安装Elasticsearch7.6.2的教程
  • 教你使用docker安装elasticsearch和head插件的方法

ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?

ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?

先了解一下数据的分类

结构化数据
又可以称之为行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据。其实就是可以能够用数据或者统一的结构加以表示的数据。比如在数据表存储商品的库存,可以用整型表示,存储价格可以用浮点型表示,再比如给用户存储性别,可以用枚举表示,这都是结构化数据。

非结构化数据
无法用数字或者统一的结构表示的数据,称之为飞结构化数据。如:文本、图像、声音、网页。
其实结构化数据又数据非结构化数据。商品标题、描述、文章描述都是文本,其实文本就是非结构化数据。那么就可以说非结构化数据即为全文数据。

什么是全文检索?

一种将文件或者数据库中所有文本与检索项相匹配的文字资料检索方法,称之为全文检索。

全文检索的两种方法

顺序扫描法:将数据表的所有数据逐个扫描,再对文字描述扫描,符合条件的筛选出来,非常慢!
索引扫描法:全文检索的基本思路,也就是将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对快的目的。

全文检索的过程:
先索引的创建,然后索引搜索

为什么要选择用 ElasticSearch?

全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选。
Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。
分布式的实时文件存储,每个字段都被索引可被搜索。
分布式的实时分析搜索引擎。
可以扩展到上百台服务器,处理 PB 级别结构化或者非结构化数据。
所有功能集成在一个服务器里,可以通过 RESTful API、各种语言的客户端甚至命令与之交互。
上手容易,提供了很多合理的缺省值,开箱即用,学习成本低。
可以免费下载、使用和修改。
配置灵活,比 Sphinx 灵活的多。

关于第14篇:一文读懂Elasticsearch强大的排序能力elasticsearch排序原理的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器、Docker部署ElasticSearch和ElasticSearch-Head、Docker部署ElasticSearch和ElasticSearch-Head的实现、ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?的相关知识,请在本站寻找。

本文标签: