当前位置: 首页 > news >正文

Elasticsearch:解锁深度匹配,运用Elasticsearch DSL构建闪电般的高效模糊搜索体验

目录

Elasticsearch查询分类

叶子查询

全文检索查询

match查询

multi_match查询

精确查询

term查询

range查询

复杂查询

bool查询简单应用

bool查询实现排序和分页

bool查询实现高亮

场景分析

问题思考

解决方案

 search_after方案(推荐)

point in time方案

方案比较


Elasticsearch查询分类

Elasticsearch的查询可以分为两大类:

叶子查询(Leaf query clauses):一般是在特定的字段里查询特定值,属于简单查询,很少单独使用。

复合查询(Compound query clauses):以逻辑方式组合多个叶子查询或者更改叶子查询的行为方式。

叶子查询

全文检索查询

用分词器对用户输入搜索条件先分词,得到词条,然后再利用倒排索引搜索词条。

match查询

可以以一个分词,例如"GB"得到所有name中带“GB”的数据

# match查询所有
GET /items/_search
{
  "query": {
    "match": {
      "name": "GB"
    }
  }
}

实现效果如下:(总共有17条数据中name有“GB”)

multi_match查询

match类似的还有multi_match,区别在于可以同时对多个字段搜索,而且多个字段都要满足,语法示例:

GET /items/_search
{
  "query": {
    "multi_match": {
      "query": "电脑",
      "fields": ["name", "category"]
    }
  }
}

实现效果如下:(即name和brand都必须带“电脑”)

精确查询

不对用户输入搜索条件分词,根据字段内容精确值匹配。但只能查找keyword、数值、日期、boolean类型的字段。

term查询

# term查询所有
GET /items/_search
{
  "query": {
   "term": {
     "brand": {
       "value": "Dell"
     }
   }
  }
}

实现效果如下:(不在对搜索条件分词)

range查询


# range查询所有
GET /items/_search
{
  "query": {
   "range": {
     "price": {
       "gte": 10000,
       "lte": 200000
     }
   }
  }
}

实现效果如下:(对price范围查询: 10000<查询值<200000)

复杂查询

bool查询简单应用

GET /items/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "GB"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "brand": "Apple"
          }
        },
        {
          "range": {
            "price": {
              "gte": 100000,
              "lte": 2000000
            }
          }
        }
      ]
    }
  }
}

实现效果如下:(name中要有“GB”,brand中有“Apple”,且100000<查询值<2000000)

bool查询实现排序和分页


GET /items/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": {
        "order": "desc"
      },
      "sold": {
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 5
}

实现效果解读:查询所有数据,先以price降序排序,price相同,以sold升序排序,一页五条。

bool查询实现高亮

我们在百度,京东搜索时,关键字会变成红色,比较醒目,这叫高亮显示。

事实上elasticsearch已经提供了给搜索关键字加标签的语法,无需我们自己编码。

GET /items/_search
{
  "query": {
    "match": {
      "name": "手机"
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}

实现效果如下:(给手机加上了<em>标签)

场景分析

问题思考

  1. elasticsearch的数据一般会采用分片存储,也就是把一个索引中的数据分成N份,存储到不同节点上。这种存储方式比较有利于数据扩展,但给分页带来了一些麻烦。
  2. 比如一个索引库中有100000条数据,分别存储到4个分片,每个分片25000条数据。现在每页查询10条,查询第99页。
  3. 实现思路来分析,肯定是将所有数据排序,找出前1000名,截取其中的990~1000的部分。但问题来了,我们如何才能找到所有数据中的前1000名呢?
  4. 要知道每一片的数据都不一样,第1片上的第900~1000,在另1个节点上并不一定依然是900~1000名。所以我们只能在每一个分片上都找出排名前1000的数据,然后汇总到一起,重新排序,才能找出整个索引库中真正的前1000名。

解决方案

 search_after方案(推荐)

search_after提供了一种基于上一次查询结果中最后一个文档的排序值来“继续”下一页的方式。这要求每次查询都必须带上前一次查询结果中的排序值,从而避免了深度分页的问题。

GET /_search
{
    "size": 10,
    "query": {
        "match": {
            "title": "elasticsearch"
        }
    },
    "search_after": [123456], // 上一个查询结果中的排序值
    "sort": [
        {"_id": "desc"}
    ]
}

point in time方案

从Elasticsearch 7.10版本开始引入的point in time功能,提供了比scroll(一个过时的方案,官方弃用)更灵活的方式来遍历结果集。与scroll不同,point in time不会自动关闭搜索上下文,而是需要显式地关闭它,这样可以在一定程度上减少资源消耗。

POST /my-index/_pit?keep_alive=1m
{}

GET /_search
{
    "size": 10,
    "query": {
        "match": {
            "title": "elasticsearch"
        }
    },
    "pit": {
        "id": "wmx3UmRBY1VnVUJqQlNvMzZQRVhBQT09LS1RY1hZRkRBPT0=",
        "keep_alive": "1m"
    },
    "sort": [{"_id": "asc"}]
}

方案比较

search_after 是解决前端深度分页的最佳选择,因为它效率高且易于实现。(简单)

point in time 提供了更细粒度的控制,特别适合长时间运行的数据处理任务,并有助于优化资源管理。

相关文章:

  • CentOS 7 中安装 Docker和Docker Compose
  • 实战 Elasticsearch:快速上手与深度实践-2.2.3案例:电商订单日志每秒10万条写入优化
  • 基于OFDR的层压陆相页岩油储层中非对称裂缝群传播的分布式光纤监测
  • 可终身授权的外国工具,不限次数使用!PDF转CAD的软件
  • WeakAuras Lua Script TOC
  • .h264/.h265文件 前端直接播放
  • iBeacon数据包全解析:读懂BLE广播包中的定位密码
  • 网页复制小妙招
  • Electron、Tauri及其它跨平台方案终极对比
  • 用不同语言写力扣题的思考:如何选择最适合的编程语言
  • Spark核心之02:常用算子详解
  • 软考高级信息系统项目管理师笔记-第8章项目整合管理
  • 园区能耗管理新趋势——构建能源数字化体系,迈向低碳未来
  • 结构体位域操作,和共用体配合使用
  • 数据集/API 笔记 新加坡相对湿度数据
  • 基于nginx的灰度发布解决方案
  • WPF 如何使文本显示控件支持显示内容滚动显示
  • Oracle 数据库基础入门(五):限制查询与范式三约定深度解析
  • 15分钟实战:SpringBoot + Vue2快速构建AI对话系统(集成DeepSeek)
  • 进程间通信方式:对列、管道、共享内存
  • 举牌超200轮!中铁建7.76亿元竞得北京通州梨园宅地
  • 三位成功女性,如何应对失败
  • 4月份全国93个国家气象站日最高气温达到或突破极值
  • 利物浦提前四轮英超夺冠,顶级联赛冠军数追平曼联
  • 5145篇报道中的上海车展:40年,什么变了?
  • 湖南小伙“朱雀玄武敕令”提交申请改名为“朱咸宁”