精华内容
参与话题
问答
  • Elasticsearch配置文件(elasticsearch.yml)详解

    万次阅读 多人点赞 2019-07-31 19:26:52
    ##################### Elasticsearch Configuration Example ##################### # # 只是挑些重要的配置选项进行注释,其实自带的已经有非常细致的英文注释了! # https://www.elastic.co/g...

     原文地址:https://my.oschina.net/Yumikio/blog/805877

    ##################### Elasticsearch Configuration Example ##################### 
    #
    # 只是挑些重要的配置选项进行注释,其实自带的已经有非常细致的英文注释了!
    # https://www.elastic.co/guide/en/elasticsearch/reference/current/modules.html
    #
    ################################### Cluster ################################### 
    # 代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的. 
    # es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。 
    # cluster.name可以确定你的集群名称,当你的elasticsearch集群在同一个网段中elasticsearch会自动的找到具有相同cluster.name的elasticsearch服务. 
    # 所以当同一个网段具有多个elasticsearch集群时cluster.name就成为同一个集群的标识. 
    
    # cluster.name: elasticsearch 
    
    #################################### Node ##################################### 
    # https://www.elastic.co/guide/en/elasticsearch/reference/5.1/modules-node.html#master-node
    # 节点名称同理,可自动生成也可手动配置. 
    # node.name: node-1
    
    # 允许一个节点是否可以成为一个master节点,es是默认集群中的第一台机器为master,如果这台机器停止就会重新选举master. 
    # node.master: true 
    
    # 允许该节点存储数据(默认开启) 
    # node.data: true 
    
    # 配置文件中给出了三种配置高性能集群拓扑结构的模式,如下: 
    # 1. 如果你想让节点从不选举为主节点,只用来存储数据,可作为负载器 
    # node.master: false 
    # node.data: true 
    # node.ingest: false
    
    # 2. 如果想让节点成为主节点,且不存储任何数据,并保有空闲资源,可作为协调器 
    # node.master: true 
    # node.data: false
    # node.ingest: false 
    
    # 3. 如果想让节点既不称为主节点,又不成为数据节点,那么可将他作为搜索器,从节点中获取数据,生成搜索结果等 
    # node.master: false 
    # node.data: false 
    # node.ingest: true (可不指定默认开启)
    
    # 4. 仅作为协调器 
    # node.master: false 
    # node.data: false
    # node.ingest: false
    
    # 监控集群状态有一下插件和API可以使用: 
    # Use the Cluster Health API [http://localhost:9200/_cluster/health], the 
    # Node Info API [http://localhost:9200/_nodes] or GUI tools # such as <http://www.elasticsearch.org/overview/marvel/>, 
    # <http://github.com/karmi/elasticsearch-paramedic>, 
    # <http://github.com/lukas-vlcek/bigdesk> and 
    # <http://mobz.github.com/elasticsearch-head> to inspect the cluster state. 
    
    # A node can have generic attributes associated with it, which can later be used 
    # for customized shard allocation filtering, or allocation awareness. An attribute 
    # is a simple key value pair, similar to node.key: value, here is an example: 
    # 每个节点都可以定义一些与之关联的通用属性,用于后期集群进行碎片分配时的过滤
    # node.rack: rack314 
    
    # 默认情况下,多个节点可以在同一个安装路径启动,如果你想让你的es只启动一个节点,可以进行如下设置
    # node.max_local_storage_nodes: 1 
    
    #################################### Index #################################### 
    # 设置索引的分片数,默认为5 
    #index.number_of_shards: 5 
    
    # 设置索引的副本数,默认为1: 
    #index.number_of_replicas: 1 
    
    # 配置文件中提到的最佳实践是,如果服务器够多,可以将分片提高,尽量将数据平均分布到大集群中去
    # 同时,如果增加副本数量可以有效的提高搜索性能 
    # 需要注意的是,"number_of_shards" 是索引创建后一次生成的,后续不可更改设置 
    # "number_of_replicas" 是可以通过API去实时修改设置的 
    
    #################################### Paths #################################### 
    # 配置文件存储位置 
    # path.conf: /path/to/conf 
    
    # 数据存储位置(单个目录设置) 
    # path.data: /path/to/data 
    # 多个数据存储位置,有利于性能提升 
    # path.data: /path/to/data1,/path/to/data2 
    
    # 临时文件的路径 
    # path.work: /path/to/work 
    
    # 日志文件的路径 
    # path.logs: /path/to/logs 
    
    # 插件安装路径 
    # path.plugins: /path/to/plugins 
    
    #################################### Plugin ################################### 
    # 设置插件作为启动条件,如果一下插件没有安装,则该节点服务不会启动 
    # plugin.mandatory: mapper-attachments,lang-groovy 
    
    ################################### Memory #################################### 
    # 当JVM开始写入交换空间时(swapping)ElasticSearch性能会低下,你应该保证它不会写入交换空间 
    # 设置这个属性为true来锁定内存,同时也要允许elasticsearch的进程可以锁住内存,linux下可以通过 `ulimit -l unlimited` 命令 
    # bootstrap.mlockall: true 
    
    # 确保 ES_MIN_MEM 和 ES_MAX_MEM 环境变量设置为相同的值,以及机器有足够的内存分配给Elasticsearch 
    # 注意:内存也不是越大越好,一般64位机器,最大分配内存别才超过32G 
    
    ############################## Network And HTTP ############################### 
    # 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0 
    # network.bind_host: 192.168.0.1 
    
    # 设置其它节点和该节点交互的ip地址,如果不设置它会自动设置,值必须是个真实的ip地址 
    # network.publish_host: 192.168.0.1 
    
    # 同时设置bind_host和publish_host上面两个参数 
    # network.host: 192.168.0.1 
    
    # 设置节点间交互的tcp端口,默认是9300 
    # transport.tcp.port: 9300 
    
    # 设置是否压缩tcp传输时的数据,默认为false,不压缩
    # transport.tcp.compress: true 
    
    # 设置对外服务的http端口,默认为9200 
    # http.port: 9200 
    
    # 设置请求内容的最大容量,默认100mb 
    # http.max_content_length: 100mb 
    
    # 使用http协议对外提供服务,默认为true,开启 
    # http.enabled: false 
    
    ###################### 使用head等插件监控集群信息,需要打开以下配置项 ###########
    # http.cors.enabled: true
    # http.cors.allow-origin: "*"
    # http.cors.allow-credentials: true
    
    ################################### Gateway ################################### 
    # gateway的类型,默认为local即为本地文件系统,可以设置为本地文件系统 
    # gateway.type: local 
    
    # 下面的配置控制怎样以及何时启动一整个集群重启的初始化恢复过程 
    # (当使用shard gateway时,是为了尽可能的重用local data(本地数据)) 
    
    # 一个集群中的N个节点启动后,才允许进行恢复处理 
    # gateway.recover_after_nodes: 1 
    
    # 设置初始化恢复过程的超时时间,超时时间从上一个配置中配置的N个节点启动后算起 
    # gateway.recover_after_time: 5m 
    
    # 设置这个集群中期望有多少个节点.一旦这N个节点启动(并且recover_after_nodes也符合), 
    # 立即开始恢复过程(不等待recover_after_time超时) 
    # gateway.expected_nodes: 2
    
     ############################# Recovery Throttling ############################# 
    # 下面这些配置允许在初始化恢复,副本分配,再平衡,或者添加和删除节点时控制节点间的分片分配 
    # 设置一个节点的并行恢复数 
    # 1.初始化数据恢复时,并发恢复线程的个数,默认为4 
    # cluster.routing.allocation.node_initial_primaries_recoveries: 4 
    
    # 2.添加删除节点或负载均衡时并发恢复线程的个数,默认为2 
    # cluster.routing.allocation.node_concurrent_recoveries: 2 
    
    # 设置恢复时的吞吐量(例如:100mb,默认为0无限制.如果机器还有其他业务在跑的话还是限制一下的好) 
    # indices.recovery.max_bytes_per_sec: 20mb 
    
    # 设置来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5 
    # indices.recovery.concurrent_streams: 5 
    # 注意: 合理的设置以上参数能有效的提高集群节点的数据恢复以及初始化速度 
    
    ################################## Discovery ################################## 
    # 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点.默认为1,对于大的集群来说,可以设置大一点的值(2-4) 
    # discovery.zen.minimum_master_nodes: 1 
    # 探查的超时时间,默认3秒,提高一点以应对网络不好的时候,防止脑裂 
    # discovery.zen.ping.timeout: 3s 
    
    # For more information, see 
    # <http://elasticsearch.org/guide/en/elasticsearch/reference/current/modules-discovery-zen.html> 
    
    # 设置是否打开多播发现节点.默认是true. 
    # 当多播不可用或者集群跨网段的时候集群通信还是用单播吧 
    # discovery.zen.ping.multicast.enabled: false 
    
    # 这是一个集群中的主节点的初始列表,当节点(主节点或者数据节点)启动时使用这个列表进行探测 
    # discovery.zen.ping.unicast.hosts: ["host1", "host2:port"] 
    
    # Slow Log部分与GC log部分略,不过可以通过相关日志优化搜索查询速度 
    
    ################  X-Pack ###########################################
    # 官方插件 相关设置请查看此处
    # https://www.elastic.co/guide/en/x-pack/current/xpack-settings.html
    # 
    ############## Memory(重点需要调优的部分) ################ 
    # Cache部分: 
    # es有很多种方式来缓存其内部与索引有关的数据.其中包括filter cache 
    
    # filter cache部分: 
    # filter cache是用来缓存filters的结果的.默认的cache type是node type.node type的机制是所有的索引内部的分片共享filter cache.node type采用的方式是LRU方式.即:当缓存达到了某个临界值之后,es会将最近没有使用的数据清除出filter cache.使让新的数据进入es. 
    
    # 这个临界值的设置方法如下:indices.cache.filter.size 值类型:eg.:512mb 20%。默认的值是10%。 
    
    # out of memory错误避免过于频繁的查询时集群假死 
    # 1.设置es的缓存类型为Soft Reference,它的主要特点是据有较强的引用功能.只有当内存不够的时候,才进行回收这类内存,因此在内存足够的时候,它们通常不被回收.另外,这些引用对象还能保证在Java抛出OutOfMemory异常之前,被设置为null.它可以用于实现一些常用图片的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory.在es的配置文件加上index.cache.field.type: soft即可. 
    
    # 2.设置es最大缓存数据条数和缓存失效时间,通过设置index.cache.field.max_size: 50000来把缓存field的最大值设置为50000,设置index.cache.field.expire: 10m把过期时间设置成10分钟. 
    # index.cache.field.max_size: 50000 
    # index.cache.field.expire: 10m 
    # index.cache.field.type: soft 
    
    # field data部分&&circuit breaker部分: 
    # 用于fielddata缓存的内存数量,主要用于当使用排序,faceting操作时,elasticsearch会将一些热点数据加载到内存中来提供给客户端访问,但是这种缓存是比较珍贵的,所以对它进行合理的设置. 
    
    # 可以使用值:eg:50mb 或者 30%(节点 node heap内存量),默认是:unbounded #indices.fielddata.cache.size: unbounded 
    # field的超时时间.默认是-1,可以设置的值类型: 5m #indices.fielddata.cache.expire: -1 
    
    # circuit breaker部分: 
    # 断路器是elasticsearch为了防止内存溢出的一种操作,每一种circuit breaker都可以指定一个内存界限触发此操作,这种circuit breaker的设定有一个最高级别的设定:indices.breaker.total.limit 默认值是JVM heap的70%.当内存达到这个数量的时候会触发内存回收
    
    # 另外还有两组子设置: 
    #indices.breaker.fielddata.limit:当系统发现fielddata的数量达到一定数量时会触发内存回收.默认值是JVM heap的70% 
    #indices.breaker.fielddata.overhead:在系统要加载fielddata时会进行预先估计,当系统发现要加载进内存的值超过limit * overhead时会进行进行内存回收.默认是1.03 
    #indices.breaker.request.limit:这种断路器是elasticsearch为了防止OOM(内存溢出),在每次请求数据时设定了一个固定的内存数量.默认值是40% 
    #indices.breaker.request.overhead:同上,也是elasticsearch在发送请求时设定的一个预估系数,用来防止内存溢出.默认值是1 
    
    # Translog部分: 
    # 每一个分片(shard)都有一个transaction log或者是与它有关的预写日志,(write log),在es进行索引(index)或者删除(delete)操作时会将没有提交的数据记录在translog之中,当进行flush 操作的时候会将tranlog中的数据发送给Lucene进行相关的操作.一次flush操作的发生基于如下的几个配置 
    #index.translog.flush_threshold_ops:当发生多少次操作时进行一次flush.默认是 unlimited #index.translog.flush_threshold_size:当translog的大小达到此值时会进行一次flush操作.默认是512mb 
    #index.translog.flush_threshold_period:在指定的时间间隔内如果没有进行flush操作,会进行一次强制flush操作.默认是30m #index.translog.interval:多少时间间隔内会检查一次translog,来进行一次flush操作.es会随机的在这个值到这个值的2倍大小之间进行一次操作,默认是5s 
    #index.gateway.local.sync:多少时间进行一次的写磁盘操作,默认是5s 

    原文地址:https://my.oschina.net/Yumikio/blog/805877

    展开全文
  • Elasticsearch下载安装

    万次阅读 多人点赞 2019-07-31 19:26:09
    注:Elasticsearch 需要 Java 8 环境,在安装Elasticsearch之前先安装好JDK。 1、Windows版 1.1、下载 访问官网的下载地址:https://www.elastic.co/downloads/elasticsearch,windows版的下载ZIP格式的。 如果...

    注:Elasticsearch 需要 Java 8 环境,在安装Elasticsearch之前先安装好JDK。

    1、Windows版

    1.1、下载

    访问官网的下载地址:https://www.elastic.co/downloads/elasticsearch,windows版的下载ZIP格式的。

    如果不想下载最新版的,可以点击“past releases”选择过去的版本。我这里下载的是6.2.4版本的。

    1.2、解压

    解压下载的压缩包,比如我这里是解压到了D盘根目录,会出现D:\elasticsearch-6.2.4文件夹。

    1.3、启动

    进入elasticsearch的bin目录,双击elasticsearch.bat启动服务,默认端口是9200,如下图:

    启动完成之后,在浏览器中访问http://localhost:9200/,出现如下图所示内容表明Elasticsearch启动成功。

    2、linux版(centos7)

    2.1、下载

    可以按照windows版那样从官网下载TAR格式解压包,上传到linux服务器上。

    如果你的linux可以访问外网的话,推荐直接在linux中下载,执行如下命令:

    wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.4.tar.gz

    2.2、解压

    执行解压命令:

    tar -zxvf elasticsearch-6.2.4.tar.gz

    解压完成后,会出现elasticsearch-6.2.4目录。

    2.3、启动

    执行启动命令:

    ./bin/elasticsearch

    如果你是root用户启动的话,会报"can not run elasticsearch as root"的错误。因为安全问题elasticsearch不让用root用户直接运行,所以要创建新用户,继续阅读2.4步骤。

    2.4、创建新用户

    第一步:liunx创建新用户:"adduser yjclsx",然后给创建的用户加密码:"passwd yjclsx",输入两次密码。

    第二步:切换刚才创建的用户:"su yjclsx",然后启动elasticsearch。如果显示Permission denied权限不足,则继续进行第三步。

    第三步:给新用户赋权限,因为这个用户本身就没有权限,肯定自己不能给自己付权限。所以要用root用户登录并赋予权限,chown -R yjclsx/你的elasticsearch安装目录。

    通过上面三步就可以启动elasticsearch了。

    2.5、验证启动是否成功

    如果一切正常,Elasticsearch就会在默认的9200端口运行。这时,打开另一个命令行窗口,请求该端口:

    curl localhost:9200

    如果得到如下的返回,就说明启动成功了:

    2.6、远程访问elasticsearch服务

    默认情况下,Elasticsearch 只允许本机访问,如果需要远程访问,可以修改 Elasticsearch 安装目录中的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,让任何人都可以访问,然后重新启动 Elasticsearch 。

    network.host: 0.0.0.0

    上面代码中,"network.host:"和"0.0.0.0"中间有个空格,不能忽略,不然启动会报错。线上服务不要这样设置,要设成具体的 IP。

    2.7、常见错误及其解决方式

    错误一:max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]

    解决:执行下面的命令:

    sudo sysctl -w vm.max_map_count=262144

    错误二:max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]

    解决:执行下面的命令:

    sudo vim /etc/security/limits.conf

    在limits.conf最下方加入下面两行(这里的yjclsx是之前2.4步骤中新建的用户名):

    yjclsx hard nofile 65536
    yjclsx soft nofile 65536

     

    展开全文
  • 2019年常见Elasticsearch 面试题答案详细解析(下)

    千次阅读 多人点赞 2019-12-26 15:51:03
    1.Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎。 (1)查询 : Elasticsearch 允许执行和合并多种类型的搜索 — 结构化、非结构化、地理位置、度量指标 — 搜索方式随心而变。 (2)分析 : ...

    前言

    1.Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎。

    (1)查询 : Elasticsearch 允许执行和合并多种类型的搜索 — 结构化、非结构化、地理位置、度量指标 — 搜索方式随心而变。

    (2)分析 : 找到与查询最匹配的十个文档是一回事。但是如果面对的是十亿行日志,又该如何解读呢?Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和模式。

    (3)速度 : Elasticsearch 很快。真的,真的很快。

    (4)可扩展性 : 可以在笔记本电脑上运行。 也可以在承载了 PB 级数据的成百上千台服务器上运行。

    (5)弹性 : Elasticsearch 运行在一个分布式的环境中,从设计之初就考虑到了这一点。

    (6)灵活性 : 具备多个案例场景。数字、文本、地理位置、结构化、非结构化。所有的数据类型都欢迎。

    (7)HADOOP & SPARK : Elasticsearch + Hadoop

    2.Elasticsearch是一个高度可伸缩的开源全文搜索和分析引擎。它允许您快速和接近实时地存储、搜索和分析大量数据。

    这里有一些使用Elasticsearch的用例:

    (1)你经营一个网上商店,你允许你的顾客搜索你卖的产品。在这种情况下,您可以使用Elasticsearch来存储整个产品目录和库存,并为它们提供搜索和自动完成建议。

    (2)你希望收集日志或事务数据,并希望分析和挖掘这些数据,以查找趋势、统计、汇总或异常。在这种情况下,你可以使用loghide (Elasticsearch/ loghide /Kibana堆栈的一部分)来收集、聚合和解析数据,然后让loghide将这些数据输入到Elasticsearch中。一旦数据在Elasticsearch中,你就可以运行搜索和聚合来挖掘你感兴趣的任何信息。

    (3)你运行一个价格警报平台,允许精通价格的客户指定如下规则:“我有兴趣购买特定的电子设备,如果下个月任何供应商的产品价格低于X美元,我希望得到通知”。在这种情况下,你可以抓取供应商的价格,将它们推入到Elasticsearch中,并使用其反向搜索(Percolator)功能来匹配价格走势与客户查询,并最终在找到匹配后将警报推送给客户。

    (4)你有分析/业务智能需求,并希望快速调查、分析、可视化,并对大量数据提出特别问题(想想数百万或数十亿的记录)。在这种情况下,你可以使用Elasticsearch来存储数据,然后使用Kibana (Elasticsearch/ loghide /Kibana堆栈的一部分)来构建自定义仪表板,以可视化对您来说很重要的数据的各个方面。此外,还可以使用Elasticsearch聚合功能对数据执行复杂的业务智能查询。

    Elasticsearch面试题

    1、详细描述一下 Elasticsearch 更新和删除文档的过程。

    2、详细描述一下 Elasticsearch 搜索的过程。

    3、在 Elasticsearch 中,是怎么根据一个词找到对应的倒排索引的?

    4、Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?

    5、对于 GC 方面,在使用 Elasticsearch 时要注意什么?

    6、Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?

    7、在并发情况下,Elasticsearch 如果保证读写一致?

    8、如何监控 Elasticsearch 集群状态?

    9、介绍下你们电商搜索的整体技术架构。

    10、介绍一下你们的个性化搜索方案?

    11、是否了解字典树?

    12、拼写纠错是如何实现的?

     

    1、详细描述一下 Elasticsearch 更新和删除文档的过程。

    (1)删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不能被删除或者改动以展示其变更;

    (2)磁盘上的每个段都有一个相应的.del 文件。当删除请求发送后,文档并没有真的被删除,而是在.del 文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del 文件中被标记为删除的文档将不会被写入新段。

    (3)在新的文档被创建时,Elasticsearch 会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del 文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。

     

    2、详细描述一下 Elasticsearch 搜索的过程。

    (1)搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;

    (2)在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。

    PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 MemoryBuffer,所以搜索是近实时的。

    (3)每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。

    (4)接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰 富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。

    (5)补充:Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。*

     

    3、在 Elasticsearch 中,是怎么根据一个词找到对应的倒排索引的?

    (1)Lucene的索引过程,就是按照全文检索的基本过程,将倒排表写成此文件格式的过程。

    (2)Lucene的搜索过程,就是按照此文件格式将索引进去的信息读出来,然后计算每篇文档打分(score)的过程。

     

    4、Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?

    (1)64 GB 内存的机器是非常理想的, 但是 32 GB 和 16 GB 机器也是很常见的。少于 8 GB 会适得其反。

    (2)如果你要在更快的 CPUs 和更多的核心之间选择,选择更多的核心更好。多个内核提供的额外并发远胜过稍微快一点点的时钟频率。

    (3)如果你负担得起 SSD,它将远远超出任何旋转介质。 基于 SSD 的节点,查询和索引性能都有提升。如果你负担得起,SSD 是一个好的选择。

    (4)即使数据中心们近在咫尺,也要避免集群跨越多个数据中心。绝对要避免集群跨越大的地理距离。

    (5)请确保运行你应用程序的 JVM 和服务器的 JVM 是完全一样的。 在Elasticsearch 的几个地方,使用 Java 的本地序列化。

    (6)通过设置 gateway.recover_after_nodes、gateway.expected_nodes、gateway.recover_after_time 可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟。

    (7)Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。最好使用单播代替组播。

    (8)不要随意修改垃圾回收器(CMS)和各个线程池的大小。

    (9)把你的内存的(少于)一半给 Lucene(但不要超过 32 GB!),通过ES_HEAP_SIZE 环境变量设置。

    (10)内存交换到磁盘对服务器性能来说是致命的。如果内存交换到磁盘上,一个100 微秒的操作可能变成 10 毫秒。 再想想那么多 10 微秒的操作时延累加起来。 不难看出 swapping 对于性能是多么可怕。

    (11)Lucene 使用了大 量 的文件。同时,Elasticsearch 在节点和 HTTP 客户端之间进行通信也使用了大量的套接字。 所有这一切都需要足够的文件描述符。你应该增加你的文件描述符,设置一个很大的值,如 64,000。

    补充:索引阶段性能提升方法

    (1)使用批量请求并调整其大小:每次批量数据 5–15 MB 大是个不错的起始点。

    (2)存储:使用 SSD

    (3)段和合并:Elasticsearch 默认值是 20 MB/s,对机械磁盘应该是个不错的设置。如果你用的是 SSD,可以考虑提高到 100–200 MB/s。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。另外还可以增加index.translog.flush_threshold_size 设置,从默认的 512 MB 到更大一些的值,比如 1 GB,这可以在一次清空触发的时候在事务日志里积累出更大的段。

    (4)如果你的搜索结果不需要近实时的准确度,考虑把每个索引的index.refresh_interval 改到 30s。

    (5)如果你在做大批量导入,考虑通过设置 index.number_of_replicas: 0 关闭副本。

     

    5、对于 GC 方面,在使用 Elasticsearch 时要注意什么?

    (1)倒排词典的索引需要常驻内存,无法 GC,需要监控 data node 上 segmentmemory 增长趋势。

    (2)各类缓存,field cache, filter cache, indexing cache, bulk queue 等等,要设置合理的大小,并且要应该根据最坏的情况来看 heap 是否够用,也就是各类缓存全部占满的时候,还有 heap 空间可以分配给其他任务吗?避免采用 clear cache等“自欺欺人”的方式来释放内存。

    (3)避免返回大量结果集的搜索与聚合。确实需要大量拉取数据的场景,可以采用scan & scroll api 来实现。

    (4)cluster stats 驻留内存并无法水平扩展,超大规模集群可以考虑分拆成多个集群通过 tribe node 连接。

    (5)想知道 heap 够不够,必须结合实际应用场景,并对集群的 heap 使用情况做持续的监控。

    (6)根据监控数据理解内存需求,合理配置各类circuit breaker,将内存溢出风险降低到最低

     

    6、Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?

    Elasticsearch 提供的首个近似聚合是 cardinality 度量。它提供一个字段的基数,即该字段的 distinct 或者 unique 值的数目。它是基于 HLL 算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关。

     

    7、在并发情况下,Elasticsearch 如果保证读写一致?

    (1)可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;

    (2)另外对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。

    (3)对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置 replication 为 async 时,也可以通过设置搜索请求参数_preference 为 primary 来查询主分片,确保文档是最新版本。

     

    8、如何监控 Elasticsearch 集群状态?

    Marvel 让你可以很简单的通过 Kibana 监控 Elasticsearch。你可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标。

     

    9、介绍下你们电商搜索的整体技术架构。

     

    10、介绍一下你们的个性化搜索方案?

    基于word2vec和Elasticsearch实现个性化搜索

    (1)基于word2vec、Elasticsearch和自定义的脚本插件,我们就实现了一个个性化的搜索服务,相对于原有的实现,新版的点击率和转化率都有大幅的提升;

    (2)基于word2vec的商品向量还有一个可用之处,就是可以用来实现相似商品的推荐;

    (3)使用word2vec来实现个性化搜索或个性化推荐是有一定局限性的,因为它只能处理用户点击历史这样的时序数据,而无法全面的去考虑用户偏好,这个还是有很大的改进和提升的空间;

     

    11、是否了解字典树?

    常用字典数据结构如下所示:

    Trie 的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。它有 3 个基本性质:

    1)根节点不包含字符,除根节点外每一个节点都只包含一个字符。

    2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

    3)每个节点的所有子节点包含的字符都不相同。

    (1)可以看到,trie 树每一层的节点数是 26^i 级别的。所以为了节省空间,我们还可以用动态链表,或者用数组来模拟动态。而空间的花费,不会超过单词数×单词长度。

    (2)实现:对每个结点开一个字母集大小的数组,每个结点挂一个链表,使用左儿子右兄弟表示法记录这棵树;

    (3)对于中文的字典树,每个节点的子节点用一个哈希表存储,这样就不用浪费太大的空间,而且查询速度上可以保留哈希的复杂度 O(1)。

    12、拼写纠错是如何实现的?

    (1)拼写纠错是基于编辑距离来实现;编辑距离是一种标准的方法,它用来表示经过插入、删除和替换操作从一个字符串转换到另外一个字符串的最小操作步数;

    (2)编辑距离的计算过程:比如要计算 batyu 和 beauty 的编辑距离,先创建一个7×8 的表(batyu 长度为 5,coffee 长度为 6,各加 2),接着,在如下位置填入黑色数字。其他格的计算过程是取以下三个值的最小值:

    如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字+1。(对于 3,3 来说为 0)

    左方数字+1(对于 3,3 格来说为 2)

    上方数字+1(对于 3,3 格来说为 2)

    最终取右下角的值即为编辑距离的值 3。

     

    对于拼写纠错,我们考虑构造一个度量空间(Metric Space),该空间内任何关系满足以下三条基本条件:

    d(x,y) = 0 -- 假如 x 与 y 的距离为 0,则 x=y

    d(x,y) = d(y,x) -- x 到 y 的距离等同于 y 到 x 的距离

    d(x,y) + d(y,z) >= d(x,z) -- 三角不等式

    (1)根据三角不等式,则满足与 query 距离在 n 范围内的另一个字符转 B,其与 A的距离最大为 d+n,最小为 d-n。

    (2)BK 树的构造就过程如下:每个节点有任意个子节点,每条边有个值表示编辑距离。所有子节点到父节点的边上标注 n 表示编辑距离恰好为 n。比如,我们有棵树父节点是”book”和两个子节点”cake”和”books”,”book”到”books”的边标号 1,”book”到”cake”的边上标号 4。从字典里构造好树后,无论何时你想插入新单词时,计算该单词与根节点的编辑距离,并且查找数值为d(neweord, root)的边。递归得与各子节点进行比较,直到没有子节点,你就可以创建新的子节点并将新单词保存在那。比如,插入”boo”到刚才上述例子的树中,我们先检查根节点,查找 d(“book”, “boo”) = 1 的边,然后检查标号为1 的边的子节点,得到单词”books”。我们再计算距离 d(“books”, “boo”)=2,则将新单词插在”books”之后,边标号为 2。

    3、查询相似词如下:计算单词与根节点的编辑距离 d,然后递归查找每个子节点标号为 d-n 到 d+n(包含)的边。假如被检查的节点与搜索单词的距离 d 小于 n,则返回该节点并继续查询。比如输入 cape 且最大容忍距离为 1,则先计算和根的编辑距离 d(“book”, “cape”)=4,然后接着找和根节点之间编辑距离为 3 到5 的,这个就找到了 cake 这个节点,计算 d(“cake”, “cape”)=1,满足条件所以返回 cake,然后再找和 cake 节点编辑距离是 0 到 2 的,分别找到 cape 和cart 节点,这样就得到 cape 这个满足条件的结果。

    最后

    欢迎大家关注我的公众号【程序员追风】,2019年多家公司java面试题整理了1000多道400多页pdf文档,文章都会在里面更新,整理的资料也会放在里面。

    喜欢文章记得关注我点个赞哟,感谢支持!

    展开全文
  • SpringBoot整合Elasticsearch

    万次阅读 多人点赞 2018-11-09 18:33:42
    1 SpringBoot整合Spring Data Elasticsearch Elasticsearch提供的Java客户端有一些不太方便的地方: 很多地方需要拼接Json字符串,在java中拼接字符串有多恐怖你应该懂的 需要自己把对象序列化为json存储 查询...

    学习本章内容的前提:
    1.能独立搭建SpringBoot项目。(SpringBoot的快速入门
    2.Elasticsearch环境搭建完毕。(Elasticsearch环境搭建和介绍(Windows)

    1 前奏

    Elasticsearch提供的Java客户端有一些不太方便的地方:

    • 很多地方需要拼接Json字符串,在java中拼接字符串有多恐怖你应该懂的
    • 需要自己把对象序列化为json存储
    • 查询到结果也需要自己反序列化为对象

    因此,我们这里就不讲解原生的Elasticsearch客户端API了。

    而是学习Spring提供的套件:Spring Data Elasticsearch

    1.1 简介

    Spring Data Elasticsearch是Spring Data项目下的一个子模块。

    查看 Spring Data的官网:http://projects.spring.io/spring-data/
    在这里插入图片描述
    Spring Data 的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。

    包含很多不同数据操作的模块:
    在这里插入图片描述

    Spring Data Elasticsearch的页面:https://projects.spring.io/spring-data-elasticsearch/
    在这里插入图片描述

    特征:

    • 支持Spring的基于@Configuration的java配置方式,或者XML配置方式
    • 提供了用于操作ES的便捷工具类ElasticsearchTemplate。包括实现文档到POJO之间的自动智能映射。
    • 利用Spring的数据转换服务实现的功能丰富的对象映射
    • 基于注解的元数据映射方式,而且可扩展以支持更多不同的数据格式
    • 根据持久层接口自动生成对应实现方法,无需人工编写基本操作代码(类似mybatis,根据接口自动得到实现)。当然,也支持人工定制查询

    1.2 Elasticsearch基本概念

    Elasticsearch也是基于Lucene的全文检索库,本质也是存储数据,很多概念与MySQL类似的。

    对比关系:

    索引库(indices)--------------------------------Databases 数据库

    类型(type)-----------------------------Table 数据表
    
         文档(Document)----------------Row 行
    
    	   字段(Field)-------------------Columns 列 
    

    详细说明:

    概念 说明
    索引库(indices) indices是index的复数,代表许多的索引,
    类型(type) 类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念
    文档(document) 存入索引库原始的数据。比如每一条商品信息,就是一个文档
    字段(field) 文档中的属性
    映射配置(mappings) 字段的数据类型、属性、是否索引、是否存储等特性

    是不是与Lucene中的概念类似。

    另外,在Elasticsearch有一些集群相关的概念:

    • 索引集(Indices,index的复数):逻辑上的完整索引
    • 分片(shard):数据拆分后的各个部分
    • 副本(replica):每个分片的复制

    注意:

    Elasticsearch本身就是分布式的,因此即便你只有一个节点,Elasticsearch默认也会对你的数据进行分片和副本操作,当你向集群添加新数据时,数据也会在新加入的节点中进行平衡。

    2.1 创建SpringBoot 项目

    首先我们要新建一个SpringBoot项目,再进行Elasticsearch的整合。

    pom依赖:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.czxy</groupId>
        <artifactId>es-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>es-demo</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.4.RELEASE</version>
            <relativePath/> 
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            
            <!-- elasticsearch启动器 (必须)-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    
    

    application.properties文件配置:

    ## Elasticsearch配置文件(必须)
    ## 该配置和Elasticsearch的elasticsearch.yml中的配置信息有关
    
    spring.data.elasticsearch.cluster-name=my-application
    spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
    

    Elasticsearch的elasticsearch.yml中的配置信息如下:

    # ======================== Elasticsearch Configuration =========================
    #
    # NOTE: Elasticsearch comes with reasonable defaults for most settings.
    #       Before you set out to tweak and tune the configuration, make sure you
    #       understand what are you trying to accomplish and the consequences.
    #
    # The primary way of configuring a node is via this file. This template lists
    # the most important settings you may want to configure for a production cluster.
    #
    # Please consult the documentation for further information on configuration options:
    # https://www.elastic.co/guide/en/elasticsearch/reference/index.html
    #
    # ---------------------------------- Cluster -----------------------------------
    #
    # Use a descriptive name for your cluster:
    #
    cluster.name: my-application
    #
    # ------------------------------------ Node ------------------------------------
    #
    # Use a descriptive name for the node:
    #
    node.name: node-1
    #
    # Add custom attributes to the node:
    #
    #node.attr.rack: r1
    #
    # ----------------------------------- Paths ------------------------------------
    #
    # Path to directory where to store the data (separate multiple locations by comma):
    #
    #path.data: /path/to/data
    #
    # Path to log files:
    #
    #path.logs: /path/to/logs
    #
    # ----------------------------------- Memory -----------------------------------
    #
    # Lock the memory on startup:
    #
    #bootstrap.memory_lock: true
    #
    # Make sure that the heap size is set to about half the memory available
    # on the system and that the owner of the process is allowed to use this
    # limit.
    #
    # Elasticsearch performs poorly when the system is swapping the memory.
    #
    # ---------------------------------- Network -----------------------------------
    #
    # Set the bind address to a specific IP (IPv4 or IPv6):
    #
    network.host: 0.0.0.0
    #
    # Set a custom port for HTTP:
    #
    http.port: 9200
    #
    # For more information, consult the network module documentation.
    #
    # --------------------------------- Discovery ----------------------------------
    #
    # Pass an initial list of hosts to perform discovery when new node is started:
    # The default list of hosts is ["127.0.0.1", "[::1]"]
    #
    #discovery.zen.ping.unicast.hosts: ["host1", "host2"]
    #
    # Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):
    #
    #discovery.zen.minimum_master_nodes: 
    #
    # For more information, consult the zen discovery module documentation.
    #
    # ---------------------------------- Gateway -----------------------------------
    #
    # Block initial recovery after a full cluster restart until N nodes are started:
    #
    #gateway.recover_after_nodes: 3
    #
    # For more information, consult the gateway module documentation.
    #
    # ---------------------------------- Various -----------------------------------
    #
    # Require explicit names when deleting indices:
    #
    #action.destructive_requires_name: true
    
    http.cors.enabled: true 
    http.cors.allow-origin: "*"
    node.master: true
    node.data: true
    
    

    2.2 索引操作

    2.2.1 创建索引和映射

    SpringBoot-data-elasticsearch提供了面向对象的方式操作elasticsearch

    业务:创建一个商品对象,有这些属性:

    id,title,category,brand,price,图片地址
    
    在SpringDataElasticSearch中,只需要操作对象,就可以操作elasticsearch中的数据
    

    实体类

    首先我们准备好实体类:

    public class Item {
        private Long id;
        private String title; //标题
        private String category;// 分类
        private String brand; // 品牌
        private Double price; // 价格
        private String images; // 图片地址
    }
    

    映射—注解

    Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

    • @Document 作用在类,标记实体类为文档对象,一般有两个属性
      • indexName:对应索引库名称
      • type:对应在索引库中的类型
      • shards:分片数量,默认5
      • replicas:副本数量,默认1
    • @Id 作用在成员变量,标记一个字段作为id主键
    • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
      • type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等
        • text:存储数据时候,会自动分词,并生成索引
        • keyword:存储数据时候,不会分词建立索引
        • Numerical:数值类型,分两类
          • 基本数据类型:long、interger、short、byte、double、float、half_float
          • 浮点数的高精度类型:scaled_float
            • 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
        • Date:日期类型
          • elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
      • index:是否索引,布尔类型,默认是true
      • store:是否存储,布尔类型,默认是false
      • analyzer:分词器名称,这里的ik_max_word即使用ik分词器

    示例:

    @Document(indexName = "item",type = "docs", shards = 1, replicas = 0)
    public class Item {
    	
    	/**
    	 * @Description: @Id注解必须是springframework包下的
    	 * org.springframework.data.annotation.Id						
    	 *@Author: https://blog.csdn.net/chen_2890
    	 */
        @Id 
        private Long id;
        
        @Field(type = FieldType.Text, analyzer = "ik_max_word")
        private String title; //标题
        
        @Field(type = FieldType.Keyword)
        private String category;// 分类
        
        @Field(type = FieldType.Keyword)
        private String brand; // 品牌
        
        @Field(type = FieldType.Double)
        private Double price; // 价格
        
        @Field(index = false, type = FieldType.Keyword)
        private String images; // 图片地址
    }
    

    创建索引

    ElasticsearchTemplate中提供了创建索引的API:
    在这里插入图片描述

    • 可以根据类的信息自动生成,也可以手动指定indexName和Settings

    映射

    映射相关的API:
    在这里插入图片描述

    • 一样,可以根据类的字节码信息(注解配置)来生成映射,或者手动编写映射

    我们这里采用类的字节码信息创建索引并映射,下面是测试类代码:

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = EsDemoApplication.class)
    public class EsDemoApplicationTests {
    
        @Autowired
        private ElasticsearchTemplate elasticsearchTemplate;
    
        /**
          * @Description:创建索引,会根据Item类的@Document注解信息来创建
          * @Author: https://blog.csdn.net/chen_2890
          * @Date: 2018/9/29 0:51
           */
        @Test
        public void testCreateIndex() {
            elasticsearchTemplate.createIndex(Item.class);
        }
    

    运行testCreateIndex(),索引创建成功后打开elasticsearch-head-master插件(es-head插件的安装)查看索引信息,
    索引信息:
    在这里插入图片描述

    2.2.2 删除索引

    删除索引的API:
    在这里插入图片描述
    可以根据类名或索引名删除。

    示例:

        /**
          * @Description:删除索引
          * @Author: https://blog.csdn.net/chen_2890
          * @Date: 2018/9/29 0:50
           */     
        @Test
        public void testDeleteIndex() {
            elasticsearchTemplate.deleteIndex(Item.class);
        }
    

    运行testDeleteIndex(),索引删除成功后打开elasticsearch-head-master插件(es-head插件的安装)查看索引信息,发现item索引已经被删除。

    2.3 新增文档数据

    2.3.1 Repository接口

    Spring Data 的强大之处,就在于你不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。只要你定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能。

    来看下Repository的继承关系:
    在这里插入图片描述
    我们看到有一个ElasticsearchCrudRepository接口:

    .png)

    所以,我们只需要定义接口,然后继承它就OK了。

    	/**
          * @Description:定义ItemRepository 接口
          * @Param:
          * 	Item:为实体类
          * 	Long:为Item实体类中主键的数据类型
          * @Author: https://blog.csdn.net/chen_2890
          * @Date: 2018/9/29 0:50
           */	 
    public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
    
    }
    

    接下来,我们测试新增数据:

    2.3.2 新增一个对象

    @Autowired
    private ItemRepository itemRepository;
    
    	/**
          * @Description:定义新增方法
          * @Author: https://blog.csdn.net/chen_2890
          */
    @Test
    public void insert() {
        Item item = new Item(1L, "小米手机7", " 手机",
                             "小米", 3499.00, "http://image.baidu.com/13123.jpg");
        itemRepository.save(item);
    }
    

    运行insert(),去页面查询看看:

    OK,新增成功!

    2.3.3 批量新增

    代码:

    	/**
          * @Description:定义批量新增方法
          * @Author: https://blog.csdn.net/chen_2890
          */
    @Test
    public void insertList() {
        List<Item> list = new ArrayList<>();
        list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.baidu.com/13123.jpg"));
        list.add(new Item(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.baidu.com/13123.jpg"));
        // 接收对象集合,实现批量新增
        itemRepository.saveAll(list);
    }
    

    再次去页面查询:
    在这里插入图片描述
    OK,批量新增成功!

    2.3.4 修改

    elasticsearch中本没有修改,它的修改原理是该是先删除在新增

    修改和新增是同一个接口,区分的依据就是id。

    	/**
          * @Description:定义修改方法
          * @Author: https://blog.csdn.net/chen_2890
          */
    @Test
    public void update(){
        Item item = new Item(1L, "苹果XSMax", " 手机",
                "小米", 3499.00, "http://image.baidu.com/13123.jpg");
        itemRepository.save(item);
    }
    

    查看结果:
    在这里插入图片描述

    2.4 查询

    2.4.1 基本查询

    ElasticsearchRepository提供了一些基本的查询方法:
    在这里插入图片描述
    我们来试试查询所有:

    	/**
          * @Description:定义查询方法,含对价格的降序、升序查询
          * @Author: https://blog.csdn.net/chen_2890
          */
    	@Test
    	public void testQueryAll(){
    	    // 查找所有
            //Iterable<Item> list = this.itemRepository.findAll();
            // 对某字段排序查找所有 Sort.by("price").descending() 降序
            // Sort.by("price").ascending():升序
            Iterable<Item> list = this.itemRepository.findAll(Sort.by("price").ascending());
    
            for (Item item:list){
                System.out.println(item);
            }
        }
    

    结果:
    在这里插入图片描述

    2.4.2 自定义方法

    Spring Data 的另一个强大功能,是根据方法名称自动实现功能。

    比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。

    当然,方法名称要符合一定的约定:

    Keyword Sample
    And findByNameAndPrice
    Or findByNameOrPrice
    Is findByName
    Not findByNameNot
    Between findByPriceBetween
    LessThanEqual findByPriceLessThan
    GreaterThanEqual findByPriceGreaterThan
    Before findByPriceBefore
    After findByPriceAfter
    Like findByNameLike
    StartingWith findByNameStartingWith
    EndingWith findByNameEndingWith
    Contains/Containing findByNameContaining
    In findByNameIn(Collection<String>names)
    NotIn findByNameNotIn(Collection<String>names)
    Near findByStoreNear
    True findByAvailableTrue
    False findByAvailableFalse
    OrderBy findByAvailableTrueOrderByNameDesc

    例如,我们来按照价格区间查询,定义这样的一个方法:

    public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
    
        /**
         * @Description:根据价格区间查询
         * @Param price1
         * @Param price2
         * @Author: https://blog.csdn.net/chen_2890
         */
        List<Item> findByPriceBetween(double price1, double price2);
    }
    

    然后添加一些测试数据:

    	/**
         * @Description:准备测试数据
         * @Author: https://blog.csdn.net/chen_2890
         */
    	@Test
    	public void insertList() {
    	    List<Item> list = new ArrayList<>();
    	    list.add(new Item(1L, "小米手机7", "手机", "小米", 3299.00, "http://image.baidu.com/13123.jpg"));
    	    list.add(new Item(2L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.baidu.com/13123.jpg"));
    	    list.add(new Item(3L, "华为META10", "手机", "华为", 4499.00, "http://image.baidu.com/13123.jpg"));
    	    list.add(new Item(4L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.baidu.com/13123.jpg"));
    	    list.add(new Item(5L, "荣耀V10", "手机", "华为", 2799.00, "http://image.baidu.com/13123.jpg"));
    	    // 接收对象集合,实现批量新增
    	    itemRepository.saveAll(list);
    	}
    

    不需要写实现类,然后我们直接去运行:

    	/**
         * @Description:按照价格区间查询
         * @Author: https://blog.csdn.net/chen_2890
         */
    	@Test
    	public void queryByPriceBetween(){
    	    List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00);
    	    for (Item item : list) {
    	        System.out.println("item = " + item);
    	    }
    	}
    

    结果:
    在这里插入图片描述

    OK,测试成功!

    2.4.3 自定义查询

    先来看最基本的matchQuery:

    	/**
         * @Description:matchQuery底层采用的是词条匹配查询
         * @Author: https://blog.csdn.net/chen_2890
         */
    	@Test
    	public void testMatchQuery(){
    	    // 构建查询条件
    	    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    	    // 添加基本分词查询
    	    queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米手机"));
    	    // 搜索,获取结果
    	    Page<Item> items = this.itemRepository.search(queryBuilder.build());
    	    // 总条数
    	    long total = items.getTotalElements();
    	    System.out.println("total = " + total);
    	    for (Item item : items) {
    	        System.out.println(item);
    	    }
    	}
    
    • NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体

    • QueryBuilders.matchQuery(“title”, “小米手机”):利用QueryBuilders来生成一个查询。QueryBuilders提供了大量的静态方法,用于生成各种不同类型的查询:
      在这里插入图片描述

    • Page<item>:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:

      • totalElements:总条数

      • totalPages:总页数

      • Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据

      • 其它属性:
        在这里插入图片描述

    结果:

    在这里插入图片描述

    总的测试代码如下:

    	/**
         *
         * @Description:matchQuery
         *@Author: https://blog.csdn.net/chen_2890
         */
        @Test
        public void testMathQuery(){
            // 创建对象
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 在queryBuilder对象中自定义查询
            //matchQuery:底层就是使用的termQuery
            queryBuilder.withQuery(QueryBuilders.matchQuery("title","坚果"));
            //查询,search 默认就是分页查找
            Page<Item> page = this.itemRepository.search(queryBuilder.build());
            //获取数据
            long totalElements = page.getTotalElements();
            System.out.println("获取的总条数:"+totalElements);
    
            for(Item item:page){
                System.out.println(item);
            }
    
    
        }
    
    
        /**
         * @Description:
         * termQuery:功能更强大,除了匹配字符串以外,还可以匹配
         * int/long/double/float/....	
         * @Author: https://blog.csdn.net/chen_2890			
         */
        @Test
        public void testTermQuery(){
            NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
            builder.withQuery(QueryBuilders.termQuery("price",998.0));
            // 查找
            Page<Item> page = this.itemRepository.search(builder.build());
    
            for(Item item:page){
                System.out.println(item);
            }
        }
    	/**
         * @Description:布尔查询
         * @Author: https://blog.csdn.net/chen_2890			
         */
        @Test
        public void testBooleanQuery(){
            NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
    
            builder.withQuery(
                    QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title","华为"))
                                             .must(QueryBuilders.matchQuery("brand","华为"))
            );
    
            // 查找
            Page<Item> page = this.itemRepository.search(builder.build());
            for(Item item:page){
                System.out.println(item);
            }
        }
    
    	/**
         * @Description:模糊查询
         * @Author: https://blog.csdn.net/chen_2890			
         */
        @Test
        public void testFuzzyQuery(){
            NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
            builder.withQuery(QueryBuilders.fuzzyQuery("title","faceoooo"));
            Page<Item> page = this.itemRepository.search(builder.build());
            for(Item item:page){
                System.out.println(item);
            }
    
        }
    

    2.4.4 分页查询

    利用NativeSearchQueryBuilder可以方便的实现分页:

    	/**
         * @Description:分页查询
         * @Author: https://blog.csdn.net/chen_2890			
         */
    	@Test
    	public void searchByPage(){
    	    // 构建查询条件
    	    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    	    // 添加基本分词查询
    	    queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    	    // 分页:
    	    int page = 0;
    	    int size = 2;
    	    queryBuilder.withPageable(PageRequest.of(page,size));
    	
    	    // 搜索,获取结果
    	    Page<Item> items = this.itemRepository.search(queryBuilder.build());
    	    // 总条数
    	    long total = items.getTotalElements();
    	    System.out.println("总条数 = " + total);
    	    // 总页数
    	    System.out.println("总页数 = " + items.getTotalPages());
    	    // 当前页
    	    System.out.println("当前页:" + items.getNumber());
    	    // 每页大小
    	    System.out.println("每页大小:" + items.getSize());
    	
    	    for (Item item : items) {
    	        System.out.println(item);
    	    }
    	}
    

    结果:
    在这里插入图片描述

    可以发现,Elasticsearch中的分页是从第0页开始

    2.4.5 排序

    排序也通用通过NativeSearchQueryBuilder完成:

    	/**
         * @Description:排序查询
         * @Author: https://blog.csdn.net/chen_2890			
         */
    	@Test
    	public void searchAndSort(){
    	    // 构建查询条件
    	    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    	    // 添加基本分词查询
    	    queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    	
    	    // 排序
    	    queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
    	
    	    // 搜索,获取结果
    	    Page<Item> items = this.itemRepository.search(queryBuilder.build());
    	    // 总条数
    	    long total = items.getTotalElements();
    	    System.out.println("总条数 = " + total);
    	
    	    for (Item item : items) {
    	        System.out.println(item);
    	    }
    	}
    

    结果:
    在这里插入图片描述

    2.5 聚合(牛逼!!solr无此功能)

    聚合可以让我们极其方便的实现对数据的统计、分析。例如:

    • 什么品牌的手机最受欢迎?
    • 这些手机的平均价格、最高价格、最低价格?
    • 这些手机每月的销售情况如何?

    实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

    2.5.1 聚合基本概念

    Elasticsearch中的聚合,包含多种类型,最常用的两种,一个叫,一个叫度量

    桶(bucket)

    桶的作用,是按照某种方式对数据进行分组,每一组数据在ES中称为一个,例如我们根据国籍对人划分,可以得到中国桶英国桶日本桶……或者我们按照年龄段对人进行划分:010,1020,2030,3040等。

    Elasticsearch中提供的划分桶的方式有很多:

    • Date Histogram Aggregation:根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组
    • Histogram Aggregation:根据数值阶梯分组,与日期类似
    • Terms Aggregation:根据词条内容分组,词条内容完全匹配的为一组
    • Range Aggregation:数值和日期的范围分组,指定开始和结束,然后按段分组
    • ……

    综上所述,我们发现bucket aggregations 只负责对数据进行分组,并不进行计算,因此往往bucket中往往会嵌套另一种聚合:metrics aggregations即度量

    度量(metrics)

    分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量

    比较常用的一些度量聚合方式:

    • Avg Aggregation:求平均值
    • Max Aggregation:求最大值
    • Min Aggregation:求最小值
    • Percentiles Aggregation:求百分比
    • Stats Aggregation:同时返回avg、max、min、sum、count等
    • Sum Aggregation:求和
    • Top hits Aggregation:求前几
    • Value Count Aggregation:求总数
    • ……

    注意:在ES中,需要进行聚合、排序、过滤的字段其处理方式比较特殊,因此不能被分词。这里我们将color和make这两个文字类型的字段设置为keyword类型,这个类型不会被分词,将来就可以参与聚合

    2.5.2 聚合为桶

    桶就是分组,比如这里我们按照品牌brand进行分组:

    	/**
         * @Description:按照品牌brand进行分组
         * @Author: https://blog.csdn.net/chen_2890			
         */
    	@Test
    	public void testAgg(){
    	    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    	    // 不查询任何结果
    	    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    	    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    	    queryBuilder.addAggregation(
    	        AggregationBuilders.terms("brands").field("brand"));
    	    // 2、查询,需要把结果强转为AggregatedPage类型
    	    AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());
    	    // 3、解析
    	    // 3.1、从结果中取出名为brands的那个聚合,
    	    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    	    StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    	    // 3.2、获取桶
    	    List<StringTerms.Bucket> buckets = agg.getBuckets();
    	    // 3.3、遍历
    	    for (StringTerms.Bucket bucket : buckets) {
    	        // 3.4、获取桶中的key,即品牌名称
    	        System.out.println(bucket.getKeyAsString());
    	        // 3.5、获取桶中的文档数量
    	        System.out.println(bucket.getDocCount());
    	    }
    	
    	}
    

    显示的结果:
    在这里插入图片描述
    关键API:

    • AggregationBuilders:聚合的构建工厂类。所有聚合都由这个类来构建,看看他的静态方法:
      在这里插入图片描述
    (1)统计某个字段的数量
      ValueCountBuilder vcb=  AggregationBuilders.count("count_uid").field("uid");
    (2)去重统计某个字段的数量(有少量误差)
     CardinalityBuilder cb= AggregationBuilders.cardinality("distinct_count_uid").field("uid");
    (3)聚合过滤
    FilterAggregationBuilder fab= AggregationBuilders.filter("uid_filter").filter(QueryBuilders.queryStringQuery("uid:001"));
    (4)按某个字段分组
    TermsBuilder tb=  AggregationBuilders.terms("group_name").field("name");
    (5)求和
    SumBuilder  sumBuilder=	AggregationBuilders.sum("sum_price").field("price");
    (6)求平均
    AvgBuilder ab= AggregationBuilders.avg("avg_price").field("price");
    (7)求最大值
    MaxBuilder mb= AggregationBuilders.max("max_price").field("price"); 
    (8)求最小值
    MinBuilder min=	AggregationBuilders.min("min_price").field("price");
    (9)按日期间隔分组
    DateHistogramBuilder dhb= AggregationBuilders.dateHistogram("dh").field("date");
    (10)获取聚合里面的结果
    TopHitsBuilder thb=  AggregationBuilders.topHits("top_result");
    (11)嵌套的聚合
    NestedBuilder nb= AggregationBuilders.nested("negsted_path").path("quests");
    (12)反转嵌套
    AggregationBuilders.reverseNested("res_negsted").path("kps ");
    
    
    • AggregatedPage:聚合查询的结果类。它是Page<T>的子接口:
      在这里插入图片描述
      AggregatedPagePage功能的基础上,拓展了与聚合相关的功能,它其实就是对聚合结果的一种封装。
      在这里插入图片描述
      而返回的结果都是Aggregation类型对象,不过根据字段类型不同,又有不同的子类表示
      在这里插入图片描述

    2.5.3 嵌套聚合,求平均值

    代码:

    	/**
         * @Description:嵌套聚合,求平均值
         * @Author: https://blog.csdn.net/chen_2890			
         */
    	@Test
    	public void testSubAgg(){
    	    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    	    // 不查询任何结果
    	    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    	    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    	    queryBuilder.addAggregation(
    	        AggregationBuilders.terms("brands").field("brand")
    	        .subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
    	    );
    	    // 2、查询,需要把结果强转为AggregatedPage类型
    	    AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());
    	    // 3、解析
    	    // 3.1、从结果中取出名为brands的那个聚合,
    	    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    	    StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    	    // 3.2、获取桶
    	    List<StringTerms.Bucket> buckets = agg.getBuckets();
    	    // 3.3、遍历
    	    for (StringTerms.Bucket bucket : buckets) {
    	        // 3.4、获取桶中的key,即品牌名称  3.5、获取桶中的文档数量
    	        System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");
    	
    	        // 3.6.获取子聚合结果:
    	        InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
    	        System.out.println("平均售价:" + avg.getValue());
    	    }
    	
    	}
    

    结果:
    在这里插入图片描述

    ok,SpringBoot整合Spring Data Elasticsearch到此完结
    要是还有不太明白的地方请留言,评论必回
    要是对我的文章感兴趣的话,关注一下吧,谢谢!

    上一篇:Elasticsearch环境搭建和介绍(Windows)

    下一篇:SpringBoot整合Shiro

    给我们一个微信勾搭的机会

    在这里插入图片描述

    展开全文
  • ElasticSearch原理

    万次阅读 2020-03-25 22:08:21
    ElasticSearch是一个分布式系统, 隐藏了复杂的处理机制 分片机制:我们不用关心数据是按照什么机制分片的、最后放入到哪个分片中 分片的副本: 集群发现机制(cluster discovery):比如当前我们启动了一-个es进程,当...
  • 1. 修改pom文件配置 ...elasticsearch.version>1.7.1</elasticsearch.version> <dependency> <groupId>org.ansj</groupId> <artifactId>ansj_seg</artifactId> <c...
  • ElasticSearch简介

    万次阅读 多人点赞 2019-05-18 08:51:31
    摘自Elasticsearch-基础介绍及索引原理分析 Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单...
  • springboot集成elasticsearch注意事项

    万次阅读 多人点赞 2019-07-31 19:27:29
    一、elasticsearch基础  这里假设各位已经简单了解过elasticsearch,并不对es进入更多的,更深层次的解释,如有必要,会在写文章专门进行es讲解。  Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。...
  • Elasticsearch教程elasticsearch Client创建

    千次阅读 2018-01-11 16:12:14
    Elasticsearch 创建Client有几种方式。 首先在 Elasticsearch 的配置文件 elasticsearch.yml中。定义cluster.name。如下: cluster.name: sojson-application 创建方式一: import static org....
  • mac安装elasticsearchelasticsearch-head

    万次阅读 2019-01-13 11:09:37
    安装ES6版本 想要安装ES的前提是已经在本机安装了Java环境,由于安装ES6版本,因此安装jdk1.8及以上版本 ...$ brew install elasticsearch 启动ES和停止 $ brew services start elasticsearch $ br...
  • elasticsearch-1.7.1 elasticsearch-jdbc-1.7.1 https://github.com/jprante/elasticsearch-jdbc 插件下载及安装 ...
  • elasticsearch-head是一个界面化的集群操作和管理工具,可以对集群进行傻瓜式操作。你可以通过插件把它集成到ES(首选方式),也可以安装成一个独立webapp。elasticsearch-head主要有以下方面的操作(官网): 显示...
  • [Elasticsearch] Elasticsearch权威指南翻译目录

    万次阅读 多人点赞 2015-12-09 11:16:36
    为了方便大家能够更加快速地找到自己需要参考的那部分,对已经翻译完成的部分根据权威指南的目录做了相应目录,希望能够有所帮助。起步(Getting Started)1....[Elasticsearch] 集群的工作原理 - 第二部分英文原文链
  • Elasticsearch学习,请先看这一篇!

    万次阅读 多人点赞 2016-08-18 21:08:36
    题记:Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识、原理从初学者认知、学习的角度,从以下9个方面进行详细梳理。欢迎讨论……0. 带着问题上路——ES是如何产生的?(1)思考:大规模数据如何...
  • 什么是 Elasticsearch 想查数据就免不了搜索,搜索就离不开搜索引擎,百度、谷歌都是一个非常庞大复杂的搜索引擎,他们几乎索引了互联网上开放的所有网页和数据。然而对于我们自己的业务数据来说,肯定就没必要用...
  • 1、到官网下载Elasticsearch,https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.3.zip 2、解压成三分份 3、下载Elasticsearch的管理工具 ...
  • 1. 检查JDK版本 使用如下命令检验JDK版本: xiaosi@Qunar:~$ java -versionjava version "1.7.0_40"Java(TM) SE Runtime Environment (build 1.7.0_40-b43)Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, ...
  • docker安装ElasticSearch:7.8.0集群

    万次阅读 2020-07-05 01:20:51
    ElasticSearch集群支持动态请求的方式搭建集群和静态配置文件搭建集群 关于集群的动态连接方式官方的文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html 前置...
  • ElasticSearch映射Mapping

    万次阅读 2020-03-10 21:56:03
    什么是Mapping映射? 映射:创建索引的时候,可以预先定义字段的类型以及相关...ElasticSearch在做字段映射的时候可以定义的类型 映射的属性方法 除了定义字段的类型,还可以给字段定义相关的属性 ...
  • elasticsearch-jdbc实现MySQL同步到ElasticSearch深入详解

    万次阅读 多人点赞 2016-06-16 20:43:07
    1.如何实现mysql与elasticsearch的数据同步?逐条转换为json显然不合适,需要借助第三方工具或者自己实现。核心功能点:同步增、删、改、查同步。2、mysql与elasticsearch同步的方法有哪些?优缺点对比?目前该领域...
  • 使用此插件,您可以使用熟悉的SQL语法查询elasticsearch。您还可以在SQL中使用ES函数。 有两种方法可以使用此插件: 使用其余的api  http://localhost:9200/_sql?sql=select * from indexName limit 10 2. 或者...
  • ElasticsearchElasticsearch面试总结

    万次阅读 2018-10-20 11:54:14
    一、Elasticsearch监控的常用工具 我大概用过如下的监控插件(注意此处插件的版本,不同es的版本,监控工具的安装方式可能不一样)  1. bigdesk 统计分析和图表化elasticsearch的集群信息状态  ...
  • 详述 Elasticsearch 通过范围条件查询索引数据的方法

    万次阅读 多人点赞 2019-04-05 11:15:59
    在使用 Elasticsearch 的时候,我们可能会遇到需要**以范围为条件查询索引数据**的需求。有两种方法可以实现我们的需求: - 第一种:在服务器或者终端,使用命令来查询索引数据; - 第二种:编写程序,通过 Elastic...
  • https://www.elastic.co/guide/en/elasticsearch/reference/2.4/restart-upgrade.html 一开始是尝试使用rolling upgrade的方式升级,但是后来发现从2.x升级到5.x是一个大的升级,需要采用full restart upgrade的...
  • 有一种情况,当我们启动elasticsearch之后, 经过很长一段时间没有操作, 自己已经忘了是否已经启动了elasticsearch, 这时候我们可以通过下面的方式验证是否启动,并重新启动: step1 查找ES进程号 ps -ef | ...
  • 1.简介elasticsearch-head是一个界面化的集群操作和管理工具,可以对集群进行傻瓜式操作。你可以通过插件把它集成到es(首选方式),也可以安装成一个独立webapp。es-head主要有三个方面的操作:显示集群的拓扑,并且...

空空如也

1 2 3 4 5 ... 20
收藏数 314,764
精华内容 125,905
关键字:

search