博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【商城】Elasticsearch搜索引擎-01.构建搜索系统之查询-实战
阅读量:4119 次
发布时间:2019-05-25

本文共 6888 字,大约阅读时间需要 22 分钟。

我们都知道,Elasticsearch作为搜索引擎被广泛应用在各个领域,尤其是电子商务网站和App的检索,如下几乎囊括的商城大部分搜索使用场景查询定义,其中包括:

基本查询:简单的查询方式
  • terms:目标列包含指定词(不分词)
  • match:会把输入的“短语”进行分解成分词,分词器可自定义
  • bool match:match分解成多个词,并且是and的关系,默认是or的关系
  • match phrase:进行分词,但要指定分词之间词语的个数
  • match phrase prefix:进行分词,分词按前缀匹配
  • multi-match:作用于多个fields的match查询
  • query string:支持lucence查询语法,title:crime10+title:punishment-otitle:cat,用±表示include和exclude,可以用表示权重,例如: field^2表示权重为2,默认权重为1
  • field查询:是queyr查询的简化版本
  • ids查询:field查询的特殊情况,只针对id列
  • prefix查询:类似于term查询,按前缀必须匹配
  • fuzzy like this查询:相似文本的查询,怎么计算相似度呢
  • fuzzy like this field查询:选定title
  • fuzzy查询:模糊查询,可定义词语之间的编辑距离(fuzziness)得到
  • wildcard查询:使用* ?的term查询
  • more like this:like且设定好范围
  • range:针对数值类型范围查询,from to

Filter过滤查询 ,对查询结果过滤
  • term{“year”:2021},过滤结果中year为2021的数据
  • range :过滤结果中指定列在给定范围的数据l
  • exists :查询结果中存在某列的数据
  • missing :查询结果中缺失某列的数据
  • scripts:bool表达式 ,查询结果中满足脚本指定条件的数据
  • type :按类型过滤
  • limit :限定返回一定数量的结果
  • ids :限定返回特殊的id集合
  • not,and,or :多个条件的组合查询

组合查询 :多个条件的组合查询
  • bool:{“must”:{查询A},“should”:{查询B}}
  • boosting:查询权重,positive的分数增高,negative分数降低
  • costant score:恒定分数;
  • indices:实现在多个Index上查询;
  • custom filters score:

另外,针对Elasticsearch搜索场景,此处不选择官方提供的查询客户端(后期会@Deprecated),而是使用 作为ES检索查询客户端,可能很多伙计都知道OkHttp是一个高效的HTTP客户端,被业界广泛应用在Http请求场景,它有以下特性:

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接 连接池减少请求延时 透明的
  • GZIP压缩减少响应数据的大小
  • 缓存响应内容,避免一些完全重复的请求

1、定义查询大全

基础BaseQuery定义,以及其他枚举类型定义;

@Getterpublic abstract class BaseQuery implements Serializable {    private static final long serialVersionUID = -8937265256480681309L;    /**     * Field查询权重     */    private Float boost;    public final Q boost(Float boost){        this.boost = boost;        //noinspection unchecked        return (Q)this;    }} public static enum  ZeroTerms {    /** zero terms*/    NONE,    ALL   }  public enum  Operator {    /**操作方向*/    OR,    AND   } public enum  Order {    /**排序方向*/    ASC,    DESC }@Getter@Builderpublic class Sort implements Serializable {    private static final long serialVersionUID = -5574272690024012413L;    /**     * 排序字段     */    private String field;    /**     * 排序指令     */    private Order order;    /**     * 脚本排序     */    private Script script;    /**     * 脚本排序Filed数据类型     */    private String type;}

1.1 id查询

/** 精确查询:文档主键Id列表查询 * @author 

1.2 Exists(存在)查询

/** 存在查询 * @author 

1.3 Wildcard(通配符)查询

/* * 通配符模糊匹配查询 * @author 

1.4 Range(范围)查询

/** 范围查询 * @author 

1.5 Term(精确)查询

/** 精确匹配查询 * @author 

1.6 Terms(精确)多查询

* 多属多值精确匹配查询 * @author 

1.7 Match(分词匹配)查询

/** 分词匹配查询  * 例如:“中国杭州”->分词为“中国”、"杭州"  * @author 

1.8 MultiMatch(分词多匹配)查询

/** 分词匹配查询:多字段Match匹配查询 * @author 

1.9 Nested(嵌套)高级查询

/** 嵌套(nested)查询 * @author 

1.10 Script高级查询

/* * script查询 * @author 

2、组合查询

2.1 bool 组合查询

评分为所有子查询评分之和;

/** 组合查询,组合第2部分定义各种组合 * @author 

2.2 dix_max 组合查询

评分为与高权重子查询的打分高度相关;

@Data@Builder@EqualsAndHashCode(callSuper = true)public class DisMaxQuery extends BaseQuery
{ private static final long serialVersionUID = -3096588829428648257L; /** * 平局参数:将其他field匹配查询语句的评分也考虑其中 */ private Float tieBreaker; /** * 文档必须匹配查询内容 */ public List
must; /** * 文档必须不允许匹配查询内容 */ public List
mustNot; /** * 文档过滤匹配内容,并不影响文档匹配得分 */ public List
filter; /** * 文档匹配上可以增加相关得分,相当于or */ public List
should; /** * 一个文档分词后匹配的百分比,例如:80%, */ private String minimumShouldMatch; public DisMaxQuery addMust(BaseQuery query) { if (must == null) { must = Lists.newArrayList(); } must.add(query); return this; } public DisMaxQuery addMustNot(BaseQuery query) { if (mustNot == null) { mustNot = Lists.newArrayList(); } mustNot.add(query); return this; } public DisMaxQuery addFilter(BaseQuery query) { if (filter == null) { filter = Lists.newArrayList(); } filter.add(query); return this; } private DisMaxQuery addShould(BaseQuery query) { if (should == null) { should = Lists.newArrayList(); } should.add(query); return this; }}

3、OkHttp使用

3.1 构建OkHttp客户端

/**     * 构建OkHttp客户端     */     private static AtomicReference
INSTANCE = new AtomicReference<>(); public OkHttpClient getClient(){ for (; ;){ //Http连接对象 OkHttpClient singleton = INSTANCE.get(); if (null != singleton){ return singleton; } OkHttpClient.Builder builder = new OkHttpClient.Builder(); //定义属性-自行处理 HttpPoolProperties pool = properties.getHttpPool(); if (Objects.nonNull(pool.getCallTimeout())){ builder.callTimeout(pool.getCallTimeout(), TimeUnit.MILLISECONDS); } if (Objects.nonNull(pool.getReadTimeout())){ builder.readTimeout(pool.getReadTimeout(), TimeUnit.MILLISECONDS); } if (Objects.nonNull(pool.getWriteTimeout())){ builder.writeTimeout(pool.getWriteTimeout(), TimeUnit.MILLISECONDS); } if (Objects.nonNull(pool.getConnectTimeout())){ builder.connectTimeout(pool.getConnectTimeout(), TimeUnit.MILLISECONDS); } builder.connectionPool(new ConnectionPool(pool.getMaxIdle(), pool.getKeepAlive(), TimeUnit.MILLISECONDS)); singleton = builder.build(); if (INSTANCE.compareAndSet(null, singleton)){ return singleton; } } }

3.2 OkHttp客户端调用

/**     * OkHttp 请求封装     * @param request 请求     * @return 响应结果     * @throws IOException 异常     */    public HttpResponse call(Request request)throws IOException {        long startTime = System.currentTimeMillis();        try {            Response response = client().newCall(request).execute();            HttpResponse resp;            try {                resp = new HttpResponse();                resp.setUrl(request.url());                resp.setCode(response.code());                resp.setBody(null == response.body() ? null : Objects.requireNonNull(response.body()).string());                long cost = (System.currentTimeMillis() - startTime) / 1000;                if (cost > REQUEST_TIMEOUT) {                    log.error("[ES-Client]执行Http耗时太长,节点:{},耗时:{}", request.url().host(), cost);                    throw new RuntimeException("ES执行操作耗时太长,请检查!");                }            } catch (Exception e) {                log.error(String.format("请求[ES-Client]发生异常,节点:%s,%d", request.url().host(), request.url().port()), e);                throw e;            } finally {                if (null != response) {                    response.close();                }            }            return resp;        } catch (ConnectException e) {            //踢出lost节点            httpTargetPool.disconnect(request.url().host());            throw e;        }    }

本节仅叙述Elasticsearch的各种查询定义,以及查询客户端的选择,后续将逐步展开,逐步带大家探索如何构建搜索引擎系统。

转载地址:http://hccpi.baihongyu.com/

你可能感兴趣的文章
XAMPP Linux Frequently Asked Questions
查看>>
Active Record
查看>>
redis-cluster研究和使用
查看>>
memcache集群搭建(magent)
查看>>
Jedis访问redis集群以及crc16
查看>>
浅析http协议、cookies和session机制、浏览器缓存
查看>>
HTTP 协议详解
查看>>
HTTP协议(rfc2626)中文翻译(修订版)
查看>>
探究php底层运行机制
查看>>
推荐一些不错的计算机书籍(php c mysql linux等等)
查看>>
Hadoop,Hbase启动及用web查看hadoop运行状态
查看>>
Hbase shell命令
查看>>
深入理解Ajax原理
查看>>
Memcached 原理和使用详解(PPT/PDF)
查看>>
Memcache 详解
查看>>
Memcached源码分析之内存管理篇
查看>>
memcached内存管理分析(不同于上一篇)
查看>>
C程序内存分配
查看>>
Memcached源码剖析系列之内存存储机制(一)
查看>>
php的session机制以及自定义会话管理器
查看>>