详解TableStore模糊查询——以订单场景为例

本文涉及的产品
对象存储 OSS,20GB 3个月
日志服务 SLS,月写入数据量 50GB 1个月
阿里云盘企业版 CDE,企业版用户数5人 500GB空间
简介: # 背景 订单系统在各行各业中广泛应用,为消费者、商家后台、促销系统等第三方提供用户、产品、订单等多维度的管理和查询服务。为了挖掘出海量订单数据的潜能,丰富高效的查询必不可少。然而很多时候并不能给出完整准确的查询关键字,例如,只知道收货人姓氏,或是产品名称部分关键字,或是根据收货人手机尾号找到订单,我们将这类查询归为“模糊查询”。

背景

订单系统在各行各业中广泛应用,为消费者、商家后台、促销系统等第三方提供用户、产品、订单等多维度的管理和查询服务。
为了挖掘出海量订单数据的潜能,丰富高效的查询必不可少。然而很多时候并不能给出完整准确的查询关键字,例如,只知道收货人姓氏,或是产品名称部分关键字,或是根据收货人手机尾号找到订单,我们将这类查询归为“模糊查询”。

需求分析

订单系统,作为电商系统的“核心”,管理着订单状态、商品信息、用户信息、收货地址和支付信息,联动库存更新,为下游的仓库物流系统提供依据。在订单表设计时,需要记录上述所有信息。本文仅以海量订单管理查询为背景,摘选部分重要字段,管窥多元索引(SearchIndex)在模糊查询时的一些典型使用,整理如下:

  • 手机号前缀匹配
    覆盖SQL like语义,满足前缀匹配、后缀匹配和通配符匹配查询。
  • 产品名称模糊查询
    用户输入产品名称中部分关键字即可查出包含相关产品的订单。
  • 商品型号的实时查询提示
    只输入少量查询关键字就可召回尽可能多的匹配结果,可用于“电影名称”、“产品型号”等字段的实时查询提示。

传统解法

MySql和PostgreSQL等关系型DB支持like语法进行模糊查询,其本质就是用查询关键词去扫描并匹配每条记录的字符串内容,只适用于小规模地检索,数据规模大了以后性能非常差。

TableStore解法

表格存储(TableStore)引入多元索引(SearchIndex)功能后,完全覆盖传统SQL所支持的前缀匹配和通配符匹配,并且提供针对不同场景的精细化模糊查询功能,性能优异。本节将以电商订单为背景逐一讲解。

手机号前缀匹配

定义手机号字段consumerCell为KEYWORD类型,创建多元索引,用PrefixQuery即可对原始字段进行前缀匹配查询。例如,查询consumerCell字段以'135'开头的行,等价于SQL中子句consumerCell like '135%'。

核心代码

//创建索引
indexSchema.addFieldSchema(new FieldSchema(CONSUMER_CELL, FieldType.KEYWORD));

//查询
PrefixQuery prefixQuery = new PrefixQuery();
prefixQuery.setFieldName(CONSUMER_CELL);
prefixQuery.setPrefix("13580");

通配符查询

如同前缀查询(PrefixQuery),通配符查询(WildcardQuery)可以对原始字符串进行更灵活一些的匹配。例如,查询consumerCell字段中以'135'开头并且中间包含'8066'的行,类比SQL中子句consumerCell like '135%8066%'。在表格存储中可以把consumerCell定义为KEYWORD类型,建立多元索引,然后用WildcardQuery进行通配符匹配。要匹配的值可以是一个带有通配符的字符串,用星号("*")代表0个或多个任意字符,用问号("?")代表任意单个字符。
需要注意的是,不能以“*”开头,且模式字符长度不能超过10字节。

如何实现后缀匹配

通配符查询不能以“*”开头,若要实现后缀匹配,可将字符串翻转,再用PrefixQuery/WildcardQuery查询。

产品名称模糊查询

在订单场景中,“收货人姓名”、“产品名”和“收货地址”这类字段可能包含汉字、英文、数字等,查询时需要以“单个汉字”或“英文单词”为粒度切分字符串并建立索引。查询同理,以“单个汉字”或“英文单词”为粒度对查询关键词字符串进行分词,在索引中进行查找匹配。

例如,订单表中,某行的产品名称字段值为"Xiaomi/小米redmi note 7 pro 红米索尼4800万智能手机",期望用"xiaomi", "小米", "note", "pro"都能匹配到该条记录。可以使用默认分词器SingleWord分词器。

TEXT类型索引列默认使用SingleWord分词器,按“单个汉字”切分中文,按“单个单词”切分英文,大小写字母不敏感,且单词不会被拆分为子词。例如,字段值"Xiaomi/小米redmi note 7 pro 红米索尼4800万智能手机"会被切分为词条:"xiaomi", "小", "米", "redmi", "note", "7", "pro", "红", "米", "索", "尼", "4800", "万", "智", "能", "手", "机",并建立倒排索引。

SingleWord支持配置参数CaseSensitive设置是否大小写敏感;参数DelimitWord表示是否将单词拆成子词。例如,当设置SingleWord的参数DelimitWord=true, CaseSensitive=true,TEXT字段值"TableStore"会被切分为"Table"和"Store"。

查询时若不在乎查询关键词分词后的顺序,用MatchQuery即可满足需求。对于特定场景,对查询关键词被被分词后顺序敏感,可以考虑使用MatchPhraseQuery。

核心代码

//创建索引
//等价于:indexSchema.addFieldSchema(new FieldSchema(PRODUCT_NAME, FieldType.TEXT));
indexSchema.addFieldSchema(new FieldSchema(PRODUCT_NAME, FieldType.TEXT).setAnalyzer(FieldSchema.Analyzer.SingleWord));

//查询
MatchQuery matchQuery = new MatchQuery();
matchQuery.setFieldName(PRODUCT_NAME);
matchQuery.setText("Xiaomi/小米redmi note 7 pro 红米索尼4800万智能手机");

商品型号的实时查询提示

某些场景下,当使用者在搜索框中键入部分关键字,就召回尽可能多的结果。这样,可以避免用户输入错误的关键字,将其引导到“意中有语中无”的正确结果,提升用户体验。例如,订单表中包含某手机型号为"HUAWEI P30PRO",一种良好的查询体验是:仅当键入"P30","30"或者"PRO"时,就可以查出这行记录并反馈用户。此时,您可以考虑使用Fuzzy分词器。

Fuzzy分词器可以对字符串进行最细粒度的拆分,可以提升查询召回率,但也造成多元索引存储量膨胀,因此需要谨慎使用。其原理是设置一个“最小字符串长度窗口(minChars)”和“最大字符串长度窗口(maxChars)”,遍历[minChars, maxChars]窗口大小对TEXT类型字段值进行切分,并对所有切分后的字符串建立倒排。minChars默认为1,maxChars默认为3。

对“产品型号”建立TEXT索引,并使用Fuzzy分词器以后,字段值"HUAWEI P30PRO"会被切分为词条:"h", "hu", "hua", "u", "ua", "uaw", "a", "aw", "awe", "w", "we", "wei", "e", "ei", "i", "p", "p3", "p30", "3", "30", "30p", "0", "0p", "0pr", "pr", "pro", "r", "ro", "o",并建立倒排索引。因此,用"p30", "P30", "30", "PRO", "pro"查询时都可以匹配到。同时也可以看出,Fuzzy分词后索引数据量急剧膨胀,因此限制maxChars和minChars的差值不超过6,如果您需要自定义minChars和maxChars时需谨慎。

核心代码

//创建索引
indexSchema.addFieldSchema(new FieldSchema(PRODUCT_TYPE, FieldType.TEXT)
                .setAnalyzer(FieldSchema.Analyzer.Fuzzy)
                .setAnalyzerParameter(new FuzzyAnalyzerParameter(1, 4)));

//查询
MatchQuery matchQuery = new MatchQuery();
matchQuery.setFieldName(PRODUCT_TYPE);
matchQuery.setText("P30");

代码示例

订单表结构

以订单系统的订单表(表名order)为例,可能包含以下字段:

列名 数据类型 索引类型 字段说明
order_id_md5 string - 主键列:md5(order_id)避免热点
order_id string KEYWORD 主键列:订单id
order_status long LONG 订单状态
order_time long LONG 下单时间
pay_time long LONG 支付时间
deliver_time long LONG 发货时间
receive_time long LONG 收货时间
product_id string KEYWORD 商品id
product_name string TEXT 产品名
product_type string TEXT 产品型号
consumer_id string KEYWORD 收货人id
consumer_name string TEXT 收货人姓名
consumer_cell string KEYWORD 收货人联系方式
consumer_address string TEXT 收货地址

项目代码

完整代码在这里找到:https://github.com/aliyun/tablestore-examples/tree/master/feature/FuzzySearch

附录

除了上文提到的SingleWord和Fuzzy分词器以外,多元索引还支持以下分词器——

MaxWord分词器

MaxWord分词器将英文切分成单词,将中文切分成尽可能多的词语/词组。对中文分词时,会做多层语义分词,一般为两层,第一层按最短语义切分,第二层按最长语义切分,并将两次切分后的数组合并。例如字符串"菊花茶",第一层切分为["菊花"、"花茶"],第二层切分为["菊花茶"],合并后为["菊花"、"花茶"、"菊花茶"]。

MinWord分词器

MinWord分词器将英文切分成单词,将中文切分为尽可能少的词语/词组。对中文分词时,只会按最长语义切分,例如字符串"菊花茶",会被切分为["菊花茶"]。

Split分词器

Split分词器允许您按照自定义分隔符对字符串进行分词。例如,用字符串内容用逗号(","),将Split分词器的分隔符设置为",",可以按照","切分并构建索引。

总结

表格存储多元索引(SearchIndex)为海量订单数据提供了丰富的查询类型,而模糊查询使得用户在不给出完整准确的查询关键字就能实现近似匹配,大大提升了订单数据的查询易用性,发挥出存储的更多潜在价值。

本文以海量电商订单管理为背景,通过几个具体案例,带您了解了多元索引强大的模糊查询功能。如有更多疑问,欢迎加入我们的技术支持群:
image.png

相关实践学习
阿里云表格存储使用教程
表格存储(Table Store)是构建在阿里云飞天分布式系统之上的分布式NoSQL数据存储服务,根据99.99%的高可用以及11个9的数据可靠性的标准设计。表格存储通过数据分片和负载均衡技术,实现数据规模与访问并发上的无缝扩展,提供海量结构化数据的存储和实时访问。 产品详情:https://www.aliyun.com/product/ots
目录
相关文章
|
存储 SQL 运维
Tablestore 与 Elasticsearch 在数据库查询加速场景使用对比
过去三十年,我们从企业应用开始,经历了 PC 互联网、移动互联网的爆发式发展,到如今的产业互联网。在这些不同时代,一直变化的是应用形态,不变的是核心数据的价值。对于核心数据的存储,首选的方案是使用数据库存储,从互联网初期开始,开源关系型数据库 MySQL 成长成为了数据库存储的第一选择,关系型数据库解决了数据的快速建模,高可靠存储和快速查询,但是关系数据库中的高效查询主要依赖二级索引,如果出现索引
1649 2
Tablestore 与 Elasticsearch 在数据库查询加速场景使用对比
|
存储 SQL 人工智能
《玩转 Tablestore 入门与实战》重磅来袭! 架构、原理及场景全方面解读
表格存储 Tablestore 是阿里云自研的面向海量结构化和半结构化数据的 Serverless 多模型数据存储,采用与 Google Bigtable 类似的宽表模型,天然的分布式架构,能支撑高吞吐的数据写入以及 PB 级数据存储。 表格存储 Tablestore于 2009 年阿里云成立之初即立项研发,基于底层飞天平台从零开始构建,在 2014 年正式商业化面向公有云提供服务。历经 10 年多的打磨,目前已在阿里巴巴集团、阿里云公共云以及专有云内得到广泛应用,涵盖电商、金融风控、物联网、人工智能、大数据、社交媒体等不同业务领域,支撑钉钉、优酷、手淘、IoT、计算平台等多个内部核心 BU
17169 0
《玩转 Tablestore 入门与实战》重磅来袭! 架构、原理及场景全方面解读
|
存储 SQL 运维
基于Tablestore 实现大规模订单系统海量订单/日志数据分类存储的实践
前言:从最早的互联网高速发展、到移动互联网的爆发式增长,再到今天的产业互联网、物联网的快速崛起,各种各样新应用、新系统产生了众多订单类型的需求,比如电商购物订单、银行流水、运营商话费账单、外卖订单、设备信息等,产生的数据种类和数据量越来越多;其中订单系统就是一个非常广泛、通用的系统。而随着数据规模的快速增长、大数据技术的发展、运营水平的不断提高,包括数据消费的能力要求越来越高,这对支撑订单系统的数据库设计、存储系统也提出了更多的要求。在新的需求下,传统的经典架构面临着诸多挑战,需要进一步思考架构优化,以更好支撑业务发展;
704 0
基于Tablestore 实现大规模订单系统海量订单/日志数据分类存储的实践
|
存储 运维 NoSQL
基于Tablestore的一站式物联网存储解决方案-场景篇
## 前言 随着5G时代的来临,万物互联概念的兴起,物联网渐渐覆盖到了各行各业中。本系列文章将为大家介绍基于表格存储Tablestore的一站式物联网存储解决方案。以共享充电宝场景为例,实现物联网场景下元数据、时序数据存储,高并发更新、分析计算等需求。 ## 背景 共享经济是近年来兴起的一种概念,共享概念极大方便了人们的生活。例如共享单车、共享车位、共享充电宝等等。这些场景里包含了大量的设备元
1022 1
|
存储 SQL 分布式计算
Tablestore在本地生活用户圈选场景下的分析实践
本地生活服务近年来越来越让我们的自身生活变得便捷。包括社区服务、生活配送、同城跑腿、餐饮、电影票务、休闲娱乐、智慧出现等。已经有大量的互联网企业在其中发现商机,帮忙用户改善原有的生活方式。而这所有的服务都是基于位置的服务(Location Based Services,LBS)。位置信息是提供本地差异化服务的关键信息。如何基于位置与时
425 0
Tablestore在本地生活用户圈选场景下的分析实践
|
存储 SQL NoSQL
基于DTS+Tablestore的海量订单系统架构设计
DTS支持MySQL同步Tablestore Beta版上线,合力打造完善的订单系统。 本文主要介绍一套基于DTS与Tablestore实现一套完善的订单系统架构。实时订单数据主要针对用户侧的实时生产与修改,实例订单数据则是基于数据同步服务DTS,全、增量订阅TP库中的订单数据,从而保证Tablestore中数据与TP库数据的最终一致性。异步同步的方式不可避免的存在延时,但历史订单库在实时性上要求会适当放宽,但其派生出来的数据在服务能力与功能扩展上得到了极大的提升,尤其是Tablestore这种分布式服务能力强、下游计算生态丰富的NoSQL存储服务。
14514 0
基于DTS+Tablestore的海量订单系统架构设计
|
存储 监控 搜索推荐
海量结构化数据解决方案-表格存储场景解读
数据是驱动业务创新的最核心的资产。不同类型的数据如非结构化数据(视频、图片等)、结构化数据(订单、轨迹),面向不同业务的使用要求需要选择适合的存储引擎,能够真正发挥数据的价值。针对于海量的非强事务的海量结构化/半结构数据,表格存储一站式解决。这里详细解读该适合场景的使用解读。
4234 0
海量结构化数据解决方案-表格存储场景解读
|
新零售 存储 关系型数据库
基于TableStore的海量电商订单元数据管理
# 一、背景 订单系统存在于各行各业,如电商订单、银行流水、运营商话费账单等,是一个非常广泛、通用的系统。对于这类系统,在过去十几年发展中已经形成了经典的做法。但是随着互联网的发展,以及各企业对数据的重视,需要存储和持久化的订单量越来越大。
4883 0
|
存储 NoSQL 容灾
表格存储服务在社交应用场景的实践
阿里云的表格存储服务(http://www.aliyun.com/product/ots)是一款面向PB级结构化/半结构化数据存储和百万级高并发读写访问的NoSQL数据库服务,在移动社交场景中有着非常广发的应用,如今非常火热的钉钉也将后台的消息推送和存储功能从MySQL迁移到表格存储上,以获得更加.
5236 0
|
9月前
|
存储 索引
表格存储根据多元索引查询条件直接更新数据
表格存储是否可以根据多元索引查询条件直接更新数据?
80 3