ElasticSearch基础(7.0+版本)

2023-11-20

一、ElasticSearch的用法

ES是基于Lucene开发的分布式高性能全文检索系统,支持分布式存储,水平扩展,主要能力是:存储、搜索、分析。我目前接触过的主要有两种用法:作为二级索引提高查询效率和基于关键词的全文检索。

Lucene:java语言开发的,搜索引擎类库。特点:高性能,学习曲线陡峭,不易扩展。

高性能检索是依赖内存实现的,所以尽量保证ES内存足够存储所有数据,如果内存不足每次查询都要走磁盘肯定性能会有很大的降低。

用法一:作为二级索引

MYsql分库分表 + ES二级索引,依赖数据同步工具保证数据一致性,Mysql写同步到ES,ES数据会有一定延迟。
部署情况:3个Master节点,4个Data节点,分别部署不同的机房。(数据节点之前因为故障下了一个,一直没有补充,所以现在是3个Data节点)
请添加图片描述

用法二:全文检索

基于关键词搜索,支持精确查询、范围查询、近似匹配、模糊匹配、高亮显示等功能。
为了实现商品信息数据检索功能,部署情况:MYsql + ES,每天凌晨定时任务同步,实时更新使用双写机制保证一致性。

二、ES中的基本概念

1、文档 Document

文档可以理解为关系型数据库的一条行记录,在Es中是JSON格式存储的。下面表格可以看作3个文档数据。

id name age
1 张三 18
2 李四 20
3 李五 20

2、倒排索引

倒排索引是通过关键词(内容)查找目录页的结构。

倒排索引结构

以2.1中的数据为例,name字段的倒排索引大概结构如下:

term(单词) count(出现次数) docId:position(文档id:位置)
1 1:0
2 2:0,3:0
1 1:1
1 2:1
1 3:1
单词词典(分词词典)Term Dictionary

用B+树或者哈希结构满足高性能插入与查询。类似mysql的二级索引。上面的term栏可以理解为是一个单词词典。

倒排列表
  • 文档id
  • 词频:在文档中出现次数,用于评分
  • 位置:单词在文档中分词的位置,用于语句搜索phrase query
  • 偏移:记录单词的开始结束位置,用于高亮显示

以2.1表数据为例,Term是“李”的倒排列表

docId 词频 Position offset
2 1 0 0,1
3 1 0 0,1

3、索引段 Segment

Lucene中多个倒排索引和文档组成Segment,Segment形成后不可变更。多个Segment汇总在一起称为Lucene Index,对应Es中的Shard分片。查询时会查所有Segment然后汇总返回结果。
新文档写入会生成新的segment(与上一个新文档间隔1s以上)。

Refresh操作

Es写入文档时,先写入Index Buffer中,从Index Buffer写入Segment的操作称为Refresh,Refresh之后Index Buffer被清空。

Refresh频率:默认1秒一次,可配置。文档写入segment之后才能被搜索到,所以写入es后查询会有延迟。Index Buffer被写满时也会触发refresh,buffer默认值是分配给JVM的堆内存大小 的10%,可配置。

Segment如何落盘

segment写入磁盘比较耗时,所以refresh时先写入缓存开放查询。为了保证数据不丢失,写入index buffer时会同时写入shard的transaction log落盘,transaction log在flush时清空。

Flush落盘
  1. 调用Refresh
  2. 调用Fsync将缓存中Segment写入磁盘中。
  3. 清空transaction log

调用频率:默认30分钟调用一次或者transaction log写满时调用。

Segment Merge
  1. 合并Segment,减少Segment数量,提高搜索速度
  2. 将.del文件中的数据彻底删除,释放空间

自动merge,也可手动merge。
不同的策略频率不同,ES默认tiered合并策略 ,根据最大索引段数量判断,如果到达阈值(根据最大值计算)就开始合并。

文档的删改

因为Segment是不可变的,所以修改文档是先删除后新增,将新增的文档写入新的Segment。文档删除不立即释放空间:删除的文件记入.del文件,
如何控制并发:使用乐观锁,每个文档有版本号version。更新数据删除原来文档,然后插入一条新的文档,version+1。

4、索引 Index

这里的索引Index类似于关系型数据库的表Schema,需要倒排索引概念区分开。

Mapping设置

  1. 字段名
  2. 字段类型
  3. 是否建立倒排索引
字段类型
  1. 简单类型:text、keyword、date、integer、float、boolean、ipv4&ipv6
  2. 复杂类型:对象类型、嵌套类型
  3. 特殊类型:geo_point&geo_shape
自动判断类型参数 dynamic

有新增字段的文档写入时:

  • dynamic设为true,Mapping也会更新
  • dynamic设为false,Mapping不会更新,数据无法索引,但是数据会出现在_source中
  • dynamic设为Strict,写入文档失败

5、分片 Shard

一个索引的数据可以分为多个主分片,每个主分片又可以设置多个副本分片冗余数据。

主分片和副本分片

  1. 分片分为主分片Primary Shard和副本分片Replica Shard,主分片故障时副本分片会选出主分片,由此做到冗余数据,容灾。
  2. 主副分片都会处理查询请求,Coordinating 节点会随机选取主副分片其中一个发送请求。新增修改删除请求只能主分片处理,然后通过主从同步到副本分片。
  3. 相同的一个索引,primary shard、replica shard不能分配到同一个节点上。

主副分片数据同步规则 :
Master节点维护一个主副分片集合,写操作时由协调节点发给主分片primary shard,主分片需要将所有操作发送给副本分片执行,全部执行完之后主分片返回给协调节点结果(副本分片执行操作时是并行的)。

ES官网原文:https://www.elastic.co/guide/en/elasticsearch/reference/7.12/docs-replication.html#basic-write-model

文档映射到分片上的算法

hash算法,默认是文档id(hash(id)%shardConut),可以自定义设置,比如将相同城市的数据分到一个分片上。所以索引创建后不能改分片数,想改只能重新reindex。

问题:相关性算分不准问题

每个分片查询时的算分根据自己分片上的数据进行算分(根据分片上的词频等数据),所以主分片越多算分越不准。

解决办法:

  1. 数据量小时将主分片设置为1(这是为什么默认主分片为1的原因),如果数据量大尽量保证文档均匀分配(这样各个词出现的频率会相对均匀,算分也会差异小一点)。
  2. 搜索URL中指定DFS Query Then Fetch参数:到每个分片把分片的词频和文档的词频进行搜索然后进行一次完整的相关性算分。会耗费更多cpu和内存,性能低下,一般不建议使用。
  3. 使用shard_size设置 (1.5 * size + 10)来设置协调节点向各个分片请求的词根个数,然后在协调节点进行聚合,最后只返回size个词根给到客户端,提高聚合精确度

6、节点 Node

6.1 Master Node

作用:
  1. 处理创建删除索引请求
  2. 决定如何把分片分发到数据节点
  3. 维护更新Cluster State(集群状态信息)
最佳实践:
  1. Master节点负责单一职责(只负责集群状态信息管理)避免受到其他功能影响,集群设置多个Master Eligible节点,在Master节点故障时参与选主成为Master节点。
  2. 单一职责Master节点只需要较低配置CPU、较低配置内存和磁盘。
如何选主:

每个节点启动时默认是Master Eligible节点,集群中第一个Master Eligible节点启动时会将自己选为Master节点。所有Master Eligible节点互相ping对方,发现Master节点丢失,Node Id最低的被选举为主节点。

Cluster State(集群状态信息)
  1. 所有节点信息
  2. 所有索引和其相关的Mapping与Setting信息
  3. 分片的路由信息

所有节点都会保存集群状态信息,但是只有Master节点可以修改并同步给其他节点。

6.2 Coordinating Node

处理请求的节点,所有节点默认都是Coordinating Node节点。
Coordinating节点接收到请求,创建(删除)索引请求转给Master节点,查询数据请求转发给存储相关数据的node,每个data node都会在自己本地执行这个请求操作,同时返回结果给coordinating node,接着coordinating node会将返回过来的所有的请求结果进行缩减和合并,返回给用户。

需要高CPU和中等大小内存。

6.3 Ingest Node

数据预处理的节点,可以在文档写入文件前执行一条ingest pipeline,比如为某个字段付默认值、重命名或者split操作,还可以支持painless脚本对数据进行复杂加工(类似于Java中的过滤器)。每个节点默认都是Ingest Node。
需要高CPU、中等内存和较低的磁盘。

6.4 Data Node

可以保存数据的节点,节点启动默认就是Data Node,用于保存分片数据。
DataNode需要存储数据+计算结果,所以需要高速大容量磁盘、高CPU、高RAM内存。

6.5 冷热节点Hot&Warm架构

可以自定义节点类型,使用不同的配置节省成本。
Hot节点:处理最新的数据和常用数据
Warm节点:存储只读的不常用数据,使用大容量HDD机械硬盘节省成本

例如日志文件:
log-202011索引创建时可以指定它在hot节点,当12月份之后,使用命令动态将其指定到warm节点,ES会自动将索引中数据搬运到warm节点上。

7、节点-分片-主副分片-Segment-文档关系:

请添加图片描述

三、搜索示例

只写出请求参数和结论,返回结果需要自己在ES实例中去跑。

Query和Filter区别

query会进行相关性算分,filter不会算分并且会利用缓存来提高搜索性能。

1、设置索引结构

PUT users
{
  "mappings" : {
      "properties" : {
        "id" : {
          "type" : "long"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "lables":{
          "type":"completion"
        },
        "age" : {
          "type" : "integer"
        },
        "desc" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    },
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 2
    }
}

ignore_above关键字:超过ignore_above设置大小的字符串不会被索引或存储

2、创建数据


POST users/_doc/1
{
  "name":"张三",
  "lables":"java开发",
  "age":20,
  "desc":"every day eat"
}
POST users/_doc/2
{
  "name":"张四三",
  "lables":"java是不是开发",
  "age":30,
  "desc":"every day sleep"
}
POST users/_doc/3
{
  "name":"李四",
  "lables":"c开发",
  "age":20,
  "desc":"every day play game"
}

3、Term Query

TermQuery不会对关键字分词;matchQuery会分词然后根据分好的term查询,如果字段类型是keyword,matchQuery会自动转为termQuery。

GET users/_search
{
  "query": {
    "term": {
      "name": {
        "value": "张三"
      }
    }
  }
}

上面的命令查不出来结果,因为name被分词了,分词词典里没有“张三”这个词。这种情况name下有keyword子字段,可以使用来查出结果:

GET users/_search
{
  "query": {
    "term": {
      "name.keyword": {
        "value": "张三"
      }
    }
  }
}

4、范围查询(区间查询)

支持范围查询的类型:
数字 integer float long double
日期 date
ip

请求:

GET /users/_search
{
    "query":{
      "constant_score":{
        "filter":{
            "range":{
                "age":{
                    "gte":21,
                    "lte":100
                }
            }
        }
      }
    }
}

constant_score表示不关心词频,不评分。

5、Match Query

5.1 Match
GET users/_search
{
  "query": {
    "match": {
      "name": "张三"
    }
  }
}

会返回name=张三和张四三的数据,match全文搜索,会将关键字分词,然后去name的单词字典中匹配。

5.2 Match Phrase Query

match phrase query的分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的。

GET users/_search
{
  "query": {
    "match_phrase": {
      "name": "张三"
    }
  }
}

结果只返回name=张三的数据,因为match_phrase会保证分词都存在,顺序一致且连续。

slop=1代表两个关键字间可以有一个其他字符介入

GET /users/_search
{
    "query":{
        "match_phrase":{
            "name":{
                "query":"张三",
                "slop":1
            }
        }
    }
}

返回的结果是name=张三和张四三的数据。

6、Query String

AND表示并且,取两个分词查询结果的交集;OR 标识或者,取两个分词查询的并集。必须大写。

GET /users/_search
{
    "query":{
        "query_string": {
          "default_field": "desc",
          "query": "every AND sleep"
        }
    }
}
# 多个字段同时查询
GET /users/_search
{
    "query":{
        "query_string": {
          "fields": ["esc","name"],
          "query": "sleep OR 张"
        }
    }
}
7、BoolQuery

must、must_not、should

GET users/_search
{
  "query": {
    "bool": {
      "must": [{
        "exists":{
        	"field": "desc"
        }
      },
      {
        "match": {
          "name":  "张三"
        }
      }]
    }
  }
}
8、自动补全 Completion Suggester

用户每输入一个字符都要及时发送一个请求到后端查找匹配项,对性能要求较苛刻。Es使用了不同的数据结构,不是倒排索引:将Analyze的数据编码为FST(Finite State Transducer)和索引一起存放,FST会被ES整个加载进内存,速度很快。FST只能前缀查找。
FST是什么:
摘自:https://blog.csdn.net/AAA821/article/details/82014792
优点:
1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;
2)查询速度快。O(len(str))的查询时间复杂度。

请添加图片描述
最终我们得到了一个有向无环图。利用该结构可以很方便的进行查询,如给定一个term “dog”,我们可以通过上述结构很方便的查询存不存在,甚至我们在构建过程中可以将单词与某一数字、单词进行关联,从而实现key-value的映射。也就是它这种压缩,就是让每个节点都不会放重复值,节省了大量的空间。

自动补全请求参数:

GET users/_search
{
    "size":0,
    "suggest":{
        "article-suggester":{
            "prefix":"java",
            "completion":{
                "field":"lables"
            }
        }
    }
}

返回建议词:“java开发”和“java是不是开发”

9、近似匹配和模糊匹配
#近似匹配,一个字符差异的相近查询
GET /users/_search?q=desc:slee~1 
{
    "profile":false
}

#模糊匹配,能搜出两词相隔一个和两个单词的结果,不必须挨着
GET /users/_search?q=desc:"every sleep"~2
{
    "profile":false
}

“profile”:"false"表示不展示profile信息,profile信息可以展示查询如何被执行的。

10、分页查询
GET /users/_search
{
  "query": {
    "match_all" : {}
  },
  "from": 0,
  "size": 2
}
分页问题

查询过程Query then Fetch:
多个分片时,查询走到coordinating节点,然后coordinating node节点选取所有分片(主从分片随机选一个),分片中查询、排序拿from+size条数据,只返回排序和排名相关的信息(不包括文档document)给coordinating节点汇总。coordinating节点拿到数据后重新排序后选from到from+size个文档的id,再根据id去不同的分片获取对应的文档数据。

ES设定搜索10000条以内的数据,超过之后报错,防止深度分页问题。

问题:深度分页时,效率极低
  1. 依赖业务或产品上解决。
  2. Search After 滚动翻页,不能支持指定from参数跳到某页。
  3. Scroll Api:生成一个快照,指定多长时间有效。每次查询输入上一个scroll id,缺点:有效时间内插入新的文档无法被查到。使用场景:想将全部文档导出,可以使用scroll api;Reindex也是使用的Scroll Api功能。

Search After演示:
请求:

GET users/_search
{
  "query": {"match_all": {}},
  "sort": [
    {
      "_id": {
        "order": "asc"
      },
      "age":{
        "order": "desc"
      }
    }
  ],
  "size": 2
}

返回:

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "张三",
          "lables" : "java开发",
          "age" : 20,
          "desc" : "every day eat"
        },
        "sort" : [
          "1",
          20
        ]
      },
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "name" : "张四三",
          "lables" : "java是不是开发",
          "age" : 30,
          "desc" : "every day sleep"
        },
        "sort" : [
          "2",
          30
        ]
      }
    ]
  }
}

根据返回的sort值构建下一页请求:
将之前返回的最后一个文档的sort值赋到查询的search_after下,就会查这条数据之后的数据。必须保证sort唯一(所以加上id)

GET users/_search
{
  "query": {"match_all": {}},
  "sort": [
    {
      "_id": {
        "order": "asc"
      },
      "age":{
        "order": "desc"
      }
    }
  ],
  "search_after":[
          "2",
          30
        ],
  "size": 2
}

四、Docker Compose安装ES集群脚本

本地使用docker启动ES集群:

  1. 安装docker和docker compose,mac上docker安装时会自动安装compose。
  2. 在docker-compose.yaml文件所在的目录执行命令docker-compose up启动集群
  3. 访问Kibana:http://localhost:5601/
  4. 访问Cerebro(集群监控):http://localhost:9000/,Node address输入:http://172.17.0.1:9200地址

docker-compose.yaml 文件

version: '2.2'
services:
  es7_01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_01
    environment:
      - cluster.name=geektime
      - node.name=es7_01
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_01,es7_02
      - cluster.initial_master_nodes=es7_01,es7_02
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es7data1/data:/usr/share/elasticsearch/data
      - ./es7data1/logs:/usr/share/elasticsearch/logs
    ports:
      - 9200:9200
    networks:
      - es7net
  es7_02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.0
    container_name: es7_02
    environment:
      - cluster.name=geektime
      - node.name=es7_02
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.seed_hosts=es7_01,es7_02
      - cluster.initial_master_nodes=es7_01,es7_02
      #- xpack.security.enabled=true
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
       - ./es7data2/data:/usr/share/elasticsearch/data
       - ./es7data2/logs:/usr/share/elasticsearch/logs
    networks:
      - es7net
  cerebro:
    image: lmenezes/cerebro:0.8.3
    container_name: cerebro
    ports:
      - "9000:9000"
    command:
      - -Dhosts.0.host=http://172.17.0.1:9200
    networks:
      - es7net
  kibana:
    image: docker.elastic.co/kibana/kibana:7.1.0
    container_name: kibana7
    environment:
      - I18N_LOCALE=zh-CN
      - XPACK_GRAPH_ENABLED=true
      - TIMELION_ENABLED=true
      - XPACK_MONITORING_COLLECTION_ENABLED="true"
      - ELASTICSEARCH_SSL_VERIFY=false
      - ELASTICSEARCH_URL="http://es7_01:9200" #容器对容器,所以写容器内的端口
      - ELASTICSEARCH_HOSTS="http://es7_01:9200"
      - ELASTICSEARCH_USERNAME="kibana"
      - ELASTICSEARCH_PASSWORD="kibana"
    ports:
      - "5601:5601"
    networks:
      - es7net
networks:
  es7net:
    driver: bridge

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ElasticSearch基础(7.0+版本) 的相关文章

随机推荐

  • SpringBoot实现前端传入数值Controller层接收为枚举

    定义枚举 import com fasterxml jackson annotation JsonCreator import com fasterxml jackson annotation JsonFormat import lombo
  • ​第一本 Compose 图书上市,联想大咖教你学会 Android 全新 UI 编程

    朱江 现任联想 北京 有限公司 Android 开发工程师 从事 Android 开发工作多年 有丰富的项目经验 负责和参与开发过多款移动应用程序 同时还是多个开源项目的作者 2017 年开始在 CSDN 发表 Android 技术相关博文
  • VLAN技术原理和配置方法

    一 VLAN产生的背景 虚拟局域网 VLAN 是英文Virtual Local Area Network的缩写 随着网络规模不断扩大 网络中的广播报文也随之增加 结果就是使交换机的负担不停的加重 并且一些终端设备也会收到不希望收到的报文 V
  • 12306验证码分割

    首先要从12306上面将验证码爬取下来 保存到C images 下 from PIL import Image import os def get sub img im x y 截出方格图片 assert 0 lt x lt 3 asser
  • HTML+CSS3 5个炫酷的loading

    为了方便大家方便CV 每个loading对应一个html文件 文件下载压缩包 下载地址 https download csdn net download m0 48850204 20432352 spm 1001 2014 3001 550
  • 解决Glide加载图片闪烁的问题(感觉加载了两遍 !!!)

    今天由于项目需求的原因 需要把原来的ViewPager的长方形图片转成圆角图片 一直觉得Glide很强大 应该可以直接设置圆角图片 但是输入 之后并没有找到这个方法 顿时一大片问号飘过 下面来说说遇到的问题 1 之前Glide 3 0 都是
  • 层次聚类在MATLAB中实现

    层次聚类在MATLAB中实现 By Yang Liu 1 第一种方法 1 输入要聚类的数据 2 计算各个样本之间的欧氏距离 3 把距离化成矩阵 矩阵中的元素 X i j X ij Xij 表示第i个样本和第j个样
  • python深度学习之用lightgbm算法实现鸢尾花种类的分类任务实战源码

    本代码以sklearn包中自带的鸢尾花数据集为例 用lightgbm算法实现鸢尾花种类的分类任务 参考来源 https lightgbm readthedocs io en latest Python Intro html usr bin
  • 用户偏好分析

    1 量化用户偏好 首先将用户分类 设定用户对于产品 喜爱 的标准 比如一天浏览产品5次 计算不同分类用户 喜爱 不同产品的人数 例如 分类 A类用户 B类用户 产品1 10 40 产品2 40 10 用户偏好指某类用户更偏好某产品 例如表中
  • 机器学习实战笔记-01概览

    机器学习的主要挑战 1 数据问题 数据量不足 训练数据不具有代表性 需要可泛化的案例 注意采样偏差 数据质量差 错误 异常 缺失 形成了噪音 无关特征 特征工程 选取 提取 创建特征 2 算法问题 过拟合 噪音 模型过于复杂参数过多 欠拟合
  • 2023华为笔试机考题库【等和子数组的最小和/动态规划】

    题目描述 给定一个数组nums 将元素分为若干个组 使得每组和相等 求出满足条件的所有分组中 组内元素和的最小值 输入描述 第一行输入 m 接着输入m个数 表示此数组 数据范围 1 lt M lt 50 1 lt nums i lt 50
  • 2023-02-21 好用的一款十六进制编辑器软件Hex Editor Neo ,以十六进制字节形式查看文件有字节

    一 Hex Editor Neo是一款十六进制编辑器软件 可以在几秒钟内处理大文件的操作 能够帮助用户编辑ASCII 十六进制 十进制 float double和二进制数据的应用程序 感觉比notepad的hex查看功能更强大 用notep
  • 音视频开发开发核心知识+新手入门必看基础知识

    音视频开发是一个广泛的领域 它涉及到多个技术领域 包括音频编解码 视频编解码 媒体容器格式 流媒体传输 音视频处理等 以下是音视频开发的一些基础知识 音频编解码器 音频编解码器是将数字音频信号编码成一种压缩格式 并且能够解码压缩的音频数据以
  • android华为手机开启蓝牙耳机,华为手机如何连接蓝牙耳机? 华为手机连接蓝牙耳机方法教程介绍!...

    我们现在在用手机的时候经常会用到耳机 听歌接电话看视频都离不开耳机 但是有的时候如果觉得耳机插来插去很麻烦就可以尝试用蓝牙耳机 那么知道华为手机怎么连接蓝牙耳机吗 具体的连接方法是怎么样的呢 下面小编就给大家简单介绍一下具体的连接方法吧 连
  • 大数据面试之SQL面试题

    一 提要 作为一名数据工作人员 SQL是日常工作中最常用的数据提取 简单预处理语言 因为其使用的广泛性和易学程度也被其他岗位比如产品经理 研发广泛学习使用 本篇文章主要结合经典面试题 给出通过数据开发面试的SQL方法与实战 二 解题思路 简
  • vue3 通过自定义指令在table中滚动加载数据

    1 在utils文件中新建一个loadMore ts文件 import type Directive App from vue const debounce function func any delay any let timer any
  • Source insight 4.0 暗色主题,模仿Atom one-darkv配色方案

    我是在MAC OS 10 12下使用crossover安装的 在wine环境下装4 0有个无法解决的bug是toolbar非常的宽 所以我取消了 反正用快捷键可以代替 关于wine安装之后界面模糊的问题请参考我这个帖子http blog c
  • 【UGUI】2D头顶血条制作

    前言 近期因为需要制作玩家和敌人头顶的2D血条 查找了很多博客 发现很多都拘束于Canvas的渲染模式必须要设定为ScreenSpace Overlay 还有应该是版本原因 我的是unity2019 1 11f1 用RecttTransfo
  • json字符串,本地存储讲解localstorage 和 sessionstorage及cookie,模板字符串初识

    这里写目录标题 json字符串 json格式的使用方法 对象的深拷贝狭义实现 localstorage 和 sessionstorage的区别 cookie 封装cookie函数 模板字符串初识 json字符串 abc123truelkgs
  • ElasticSearch基础(7.0+版本)

    一 ElasticSearch的用法 ES是基于Lucene开发的分布式高性能全文检索系统 支持分布式存储 水平扩展 主要能力是 存储 搜索 分析 我目前接触过的主要有两种用法 作为二级索引提高查询效率和基于关键词的全文检索 Lucene