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}}}}
posted @ 2021-08-05 12:00  泊月居  阅读(135)  评论(0编辑  收藏  举报