• es学习记录


    1. elasticsearch

    1.1 常用命令

    Kibana 基本语法 API

    method url desc
    PUT localhost:9200/索引名称/类型名称/文档id 创建文档(指定文档id)
    POST localhost:9200/索引名称/类型名称 创建文档(随机id)
    POST localhost:9200/索引名称/_update/文档id 修改文档
    DELETE localhost:9200/索引名称/类型名称/文档id 删除文档 by id
    GET localhost:9200/索引名称/类型名称/文档id 查询文档 by id
    POST localhost:9200/索引名称/_search 查询所有文档

    新建

    #创建空库
    PUT /test2
    {
        
    }
    #创建索引 及 规定字段类型
    PUT /test3
    {
      "mappings": {
        "properties": {
          "name":{
            "type": "text"
          },
          "age":{
            "type": "integer"
          },
          "birth":{
            "type": "date"
          }
        }
      }
    }
    #创建数据
    PUT /wanghl/_doc/2
    {
      "name":"花木兰",
      "age":67,
      "tags":["战士","上单","女"]
    }
    

    删除

    #删除索引
    DELETE test2
    #删除文档
    DELETE test1/_doc/3
    

    修改

    #修改文档
    POST /test1/_update/4
    {
       "doc":{
         "name":"红桃A"
       }
    }
    

    查询

    _source 字段过滤 不写默认 select *

    #获取索引库
    GET test3
    #获取文档by文档id
    GET wanghl/_doc/2
    #根据属性查询  简写
    GET wanghl/_search?q=name:李
    #构建式查询   
    #_source    字段过滤   不写默认 select  *
    # from  size   分页
    GET /wanghl/_search
    {
      "query": {
        "match": {
          "tags": "男"
        }
      },
      "_source": ["name","tags"], 
      "from":0,
      "size":1
    }
    #多条件查询   must 相当于 and     should 相当于 or     
    GET wanghl/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "tags": "男 下路"
              }
            }
          ],
          "must_not": [
            {
              "match": {
                "age": "3"
              }
            }
          ]
        }
      }
    }
    # 查询过滤  +  高亮显示
    GET wanghl/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "tags": "男"
              }
            }
          ] ,
          "filter": [
            {
              "range": {
                "age": {
                  "gte": 10,
                  "lte": 200
                }
              }
            }
          ]  
        }
      },
      "highlight": {
        "pre_tags": "<font>",
        "post_tags": "</font>", 
        "fields": {
          "tags": {}
        }
      }
    }
    

    其中gt代表大于,gte代表大于等于,lt小于,lte小于等于

    GET website/_search
    {
        "query": {
            "range": {
                "post_date": {
                    "gte": "now-1d/d",  // 当前时间的上一天, 四舍五入到最近的一天
                    "lt":  "now/d"      // 当前时间, 四舍五入到最近的一天
                }
            }
        }
    }
    

    Elasticsearch中时间可以表示为now, 也就是系统当前时间, 也可以是以||结尾的日期字符串表示.

    在日期之后, 可以选择一个或多个数学表达式:

    • +1h —— 加1小时;
    • -1d —— 减1天;
    • /d —— 四舍五入到最近的一天

    下面是Elasticsearch支持数学表达式的时间单位:

    表达式 含义 表达式 含义
    y M
    w 星期 d
    h 小时 H 小时
    m 分钟 s

    说明: 假设系统当前时间now = 2018-10-01 12:00:00 :

    • now+1h: now的毫秒值 + 1小时, 结果是: 2018-10-01 13:00:00.
    • now-1h: now的毫秒值 - 1小时, 结果是: 2018-10-01 11:00:00.
    • now-1h/d: now的毫秒值 - 1小时, 然后四舍五入到最近的一天的起始, 结果是: 2018-10-01 00:00:00.
    • 2018.10.01||+1M/d: 2018-10-01的毫秒值 + 1月, 再四舍五入到最近一天的起始, 结果是: 2018-11-01 00:00:00.

    关于时间的四舍五入

    对日期中的日、月、小时等 进行四舍五入时, 取决于范围的结尾是包含(include)还是排除(exclude).

    向上舍入: 移动到舍入范围的最后一毫秒;

    向下舍入: 一定到舍入范围的第一毫秒.

    举例说明:

    ① "gt": "2018-12-18||/M" —— 大于日期, 需要向上舍入, 结果是2018-12-31T23:59:59.999, 也就是不包含整个12月.

    ② "gte": "2018-12-18||/M" —— 大于或等于日期, 需要向下舍入, 结果是 2018-12-01, 也就是包含整个12月.

    ③ "lt": "2018-12-18||/M" —— 小于日期, 需要向上舍入, 结果是2018-12-01, 也就是不包含整个12月.

    ④ "lte": "2018-12-18||/M" —— 小于或等于日期, 需要向下舍入, 结果是2018-12-31T23:59:59.999, 也就是包含整个12月.

    日期格式化范围查询(format)

    格式化日期查询时, 将默认使用日期field中指定的格式进行解析, 当然也可以通过format参数来覆盖默认配置.

    示例:

    GET website/_search
    {
        "query": {
            "range": {
                "post_date": {
                    "gte": "2/1/2018", 
                    "lte": "2019",
                    "format": "dd/MM/yyyy||yyyy"
                }
            }
        }
    }
    

    注意: 如果日期中缺失了部分年、月、日, 缺失的部分将被填充为unix系统的初始值, 也就是1970年1月1日.

    比如, 将dd指定为format, 像"gte": 10将转换为1970-01-10T00:00:00.000Z.

    时区范围查询(time_zone)

    如果日期field的格式允许, 也可以通过在日期值本身中指定时区, 从而将日期从另一个时区的时间转换为UTC时间, 或者为其指定特定的time_zone参数.

    GET website/_search
    {
        "query": {
            "range": {
                "post_date": {
                    "gte": "2018-01-01 00:00:00",
                    "lte": "now",
                    "format": "yyyy-MM-dd hh:mm:ss",
                    "time_zone": "+1:00"
                }
            }
        }
    }
    

    ES中的日期类型必须按照UTC时间格式存储, 所以, 上述的2018-01-01 00:00:00将被转换为2017-12-31T23:00:00 UTC.

    另外需要注意的是, now是不受time_zone影响的.

    合并查询语句

    复合(Compound) 语句 主要用于 合并其它查询语句。 比如,一个 bool 语句 允许在你需要的时候组合其它语句,无论是 must 匹配、 must_not 匹配还是 should 匹配,同时它可以包含不评分的过滤器(filters):

    {
        "bool": {
            "must":     { "match": { "tweet": "elasticsearch" }},
            "must_not": { "match": { "name":  "mary" }},
            "should":   { "match": { "tweet": "full text" }},
            "filter":   { "range": { "age" : { "gt" : 30 }} }
        }
    }
    

    2. Springboot 整合elasticsearch

    主要介绍了SpringBoot整合Spring Data Elasticsearch的过程详解

    2.1 ElasticsearchTemplate

    ​ Spring Data Elasticsearch提供了ElasticsearchTemplate工具类,实现了POJO与elasticsearch文档之间的映射elasticsearch本质也是存储数据,它不支持事物,但是它的速度远比数据库快得多,可以这样来对比lasticsearch和数据库的关系。

    • 索引(indices)--------数据库(databases)
    • 类型(type)------------数据表(table)
    • 文档(Document)---------------- 行(row)
    • 字段(Field)-------------------列(Columns )

    2.1.1 整合过程

    1,在SprinBoot工程中引入jar包

    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
    

    2,配置文件

    spring.data.elasticsearch.cluster-name=elasticsearch //名字必须和elasticsearch.yml里面的cluster.name相同spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300  #开启 Elasticsearch 仓库(默认值:true)spring.data.elasticsearch.repositories.enabled=true
    

    配置文件助记

    # ES#开启 Elasticsearch 仓库(默认值:true)spring.data.elasticsearch.repositories.enabled=true#默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300#spring.data.elasticsearch.cluster-name Elasticsearch 集群名(默认值: elasticsearch)#spring.data.elasticsearch.cluster-nodes 集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点#spring.data.elasticsearch.propertie 用来配置客户端的额外属性#存储索引的位置spring.data.elasticsearch.properties.path.home=/data/project/target/elastic#连接超时的时间spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s
    
    server.port=8080server.servlet.context-path=/ems#https://blog.csdn.net/haohaifeng002/article/details/102887921spring.elasticsearch.rest.uris=http://localhost:9200spring.elasticsearch.rest.username=elasticspring.elasticsearch.rest.password=123456
    

    配置只有一句,但需要强调下,我们的elasticsearch服务端是当前的最新版本7.4.1。Elasticsearch从7开始不推荐使用TransportClient客户端访问,8会彻底删除该客户端API的支持,推荐用High Level REST Client(见参考1),所以此处配置使用spring.elasticsearch.rest.uris,默认值为http://localhost:9200,可以是多个uri。之前如spring.data.elasticsearch.cluster-name=my-application spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300的TransportClient配置方式已被标记为过时。

    3,创建实体,并对类和属性进行标注

    @Document(indexName = "item",type = "docs", shards = 1, replicas = 0)//标记为文档类型,indexName:对应索引库名称 type:对应在索引库中的类型,shards:分片数量,默认5,replicas:副本数量,默认1public class Item {  @Id //主键  private Long id;  @Field (type = FieldType.Text, analyzer =  "ik_max_word" )  //标记为成员变量  FieldType,可以是text、long、short、date、integer等  //text:存储数据时候,会自动分词,并生成索引  keyword:存储数据时候,不会分词建立索引  analyzer:分词器名称  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) //index:是否索引  private String images;  // 图片地址
    

    4.引入模板ElasticsearchTemplate

    @Autowiredprivate ElasticsearchTemplate elasticsearchTemplate;
    

    5.创建一个索引

    //添加索引@Testpublic void addIndex() {  elasticsearchTemplate.createIndex(Item.class );}
    

    6.删除索引

    //删除索引@Testpublic void delete(){  elasticsearchTemplate.deleteIndex( "item" );}
    

    7.新增对象

    继承Repository提供的一些子接口,就能具备各种基本的CRUD功能,这里继承ElasticsearchCrudRepository

    首先定义一个对象的接口

    public interface ItemRepository  extends ElasticsearchCrudRepository<Item,Long> {}
    

    然后注入ItemRepository

    @Autowiredprivate ItemRepository itemRepository;
    

    新增对象

    //新增一个对象 @Test public void insert(){   Item item =  new Item(2L, "坚果R1" , "手机" , "锤子" , 2500.00 , "http://image.baidu.com/13123.jpg" );   //Order order = new Order(20180020,"菜单");   itemRepository.save(item);  }
    

    批量新增

    //批量新增  @Test  public void insertList(){    List<Item> list = new LinkedList<>();    list.add(new Item(9L,"华为p20","手机","华为",3500.00,"http://image.baidu.com/13123.jpg"));    list.add(new Item(10L,"华为p30","手机","华为",5450.00,"http://image.baidu.com/13123.jpg"));    list.add(new Item(11L,"华为p30 pro","手机","华为",6980.00,"http://image.baidu.com/13123.jpg"));    itemRepository.saveAll(list);  }
    

    8.查询

    //根据字段查询所有  @Test  public void queryAll(){    //升序,相应降序为dscending    Iterable<Item> items = this.itemRepository.findAll(Sort.by("price").ascending());    for (Item item : items){      System.out.println(item);    }  }
    

    9.自定义查询方法

    Spring Data 的另一个强大功能,是根据方法名称自动实现功能,你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。当然,方法名称要符合一定的约定:

    img

    使用自定义方法需要在接口里面申明方法

    public interface ItemRepository extends ElasticsearchCrudRepository<Item,Long> {  Item findByTitle(String title);  List<Item> findByPriceBetween(double price1, double price2);  List<Item> findByTitleLike(String title);}
    

    根据手机名查找手机

    //自定义方法,根据Title查询  @Test  public void findByTitle(){    Item item = this.itemRepository.findByTitle("坚果pro");    System.out.println(item);  }
    

    区间查询

    //根据区间查询  @Test  public void queryByPriceBetween(){    List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00);    for (Item item : list) {      System.out.println("item = " + item);    }  }
    

    模糊查询

    //模糊查询  @Test  public void queryLikeTitle(){    List<Item> list = this.itemRepository.findByTitleLike("R2");    for (Item item : list){      System.out.println(item);    }  }
    

    10.自定义查询

    //自定义查询,查询数目等  @Test  public void matchQuery(){    // 构建查询条件    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();    // 添加基本分词查询    queryBuilder.withQuery(QueryBuilders.matchQuery("title","坚果"));    //获取结果    Page<Item> items = (Page<Item>) this.itemRepository.findAll();    //条数    long total = items.getTotalElements();    System.out.println("total = "+total);    for (Item item : items){      System.out.println(item);    }  }关键的是NativeSearchQueryBuilder这个类
    

    分页查询

    //分页查询  @Test  public void queryByPage(){    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();    nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("category","手机"));    int page = 0;    int size = 2;    nativeSearchQueryBuilder.withPageable(PageRequest.of(page,size));    Page<Item> items = (Page<Item>) this.itemRepository.findAll();    long total = items.getTotalElements();    int totalPage = items.getTotalPages();    int nowPage = items.getNumber();    int pageSize = items.getSize();    System.out.println("总条数 = "+total);    System.out.println("总页数 = "+totalPage);    System.out.println("当前页 = "+nowPage);    System.out.println("每页大小 = "+pageSize);    for (Item item : items){      System.out.println(item);    }  }
    

    有些在复杂的可以使用es查询语句

      我们可以使用@Query注解进行查询,这样要求我们需要自己写ES的查询语句

      public interface BookRepository extends ElasticsearchRepository<Book, String> {    @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")    Page<Book> findByName(String name,Pageable pageable);}
    
     //默认的注释    //@Query("{"bool" : {"must" : {"field" : {"content" : "?"}}}}")    Page<DocBean> findByContent(String content, Pageable pageable);    @Query("{"bool" : {"must" : {"field" : {"firstCode.keyword" : "?"}}}}")    Page<DocBean> findByFirstCode(String firstCode, Pageable pageable);    @Query("{"bool" : {"must" : {"field" : {"secordCode.keyword" : "?"}}}}")    Page<DocBean> findBySecordCode(String secordCode, Pageable pageable);————————————————版权声明:本文为CSDN博主「程裕强」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/chengyuqiang/article/details/102938266
    

    方法和es查询转换:

    Keyword Sample Elasticsearch Query String
    And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
    Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
    Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
    Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
    Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
    LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
    GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
    Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
    After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
    Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
    StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
    EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
    Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
    In findByNameIn(Collection<String>names) {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
    NotIn findByNameNotIn(Collection<String>names) {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
    Near findByStoreNear Not Supported Yet !
    True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
    False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
    OrderBy findByAvailableTrueOrderByNameDesc {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
  • 相关阅读:
    abstract和virtual
    vue中 关于$emit的用法
    babel简介
    vue脚手架的使用
    RAM和ROM
    判断匿名类是否继承父类
    ABP应用层——参数有效性验证
    vue-devtools的安装与使用
    JavaScript中Object.keys用法
    vue中created、mounted、 computed,watch,method 等方法整理
  • 原文地址:https://www.cnblogs.com/jqpy1994/p/15102703.html
Copyright © 2020-2023  润新知