基于词槽的简单query匹配方法

我们在做类似搜索相关的特定服务时,通常都会遇到分词解析query,取出其中特定关键字进行检索的问题,这里提供一个简单的基于词槽的query匹配方法。

首先给出一个query示例:北京飞三亚机票多少钱?

 

我们需要达到的目标:

1.判定这个query的分类

2.解析出机票分类query中的起点和终点

3.从数据中检索对应数据并返回展示

这3个目标对应3个专业名词:1.da识别 2.pattern解析 3.召回判定。

 

下边我们来一步一步的实现这3个目标:

一、da识别:判定这个query的分类

就这个case而言还是比较简单的,我们可以给一个机票类模糊da词典,列上“机票、飞机、航班”等包含即可判定的关键词,然后给他分配一个分类id比如“1001”,当拿到query时,先用da词典按设定进行模糊或精确匹配,如果匹配上了,比如当前这个case模糊匹配上了”机票”两个字,那么da的结果就是”1001″。

这比“苹果”这种case简单多了,因为苹果可能在“品牌、水果、股票、电影”等很多分类中都存在,这种场景下da的结果就会是多个,比如“1101、1201、1301、1401”。

二、pattern匹配:解析出机票分类query中的起点和终点

da一定识别出了分类,接下来需要做的就要解析出其中的有用信息了。

我们看到,“北京飞三亚机票多少钱?”这个query中,除了关键词”机票”、起止点“北京、三亚”以外,还有”飞、多少钱、?”等其它文字,实际上,用户输入的query五花八门,比如”北京到三亚航班时刻表”,那么我们怎么才能使用一个通过的方法准确的识别出来,又不用花费太大的成本呢?

现在要讲的方法叫基于词槽的匹配方法,它有几个概念先提前解释一下:

词term:所有可能被分词切分的部分,比如“北京、飞、三亚、机票、多少、钱、多少钱、?”都是词。

词槽:用来容纳分词结果的槽位,不同的槽位代表不同的含义,比如“城市、介词、关键词”等槽位。

匹配规则pattern:枚举不同的词槽里的词可能有组合规则。比如“[起点城市][词][终点城市][关键词]”,如果query是“2015款jeep指南者4驱豪华版报价”,匹配规则是“[年款][品牌][车系][驱动模式][版型][意图]”

同义词synonym:用来做同义词转换,比如“北京飞亚龙湾航班”,亚龙湾即不是机场名,也不是机场所在的实际城市,而是个三亚的景点,而我们又想直接给用户显示结果,又想不影响检索性能,那么一个简单的办法就是用同义词把“亚龙湾”转换成“三亚”,这样就能直接用“北京”-“三亚”进行检索了。

杂质词ignore:query中包含的对检索结果无意义的词,他们对检索的结果没有影响,可以完全忽略掉,这部分词统称为杂质词,比如“多少钱、?”。因为这个case我们明确要显示航班、机票价格,所以这“多少钱、?”会无意义,但有些case时我们需要知道用户的意图和语气时,这些词可能又不是杂质词了,比如“宝马3系多少钱”,通过“多少钱”能知道用户是想查车的价格,“宝马3系图片”用户是想看车图,所以不同分类需要单独分析。

好了,了解了词槽匹配的几个概念词后,我们就开始实际实现一下:

term.dict

[from]

北京

[to]

北京

三亚

亚龙湾

[link]

[keyword]

机票

航班

pattern.dict

[from][link][to][keyword]

[from][to][keywork]

…..

synonym.dict

亚龙湾    三亚

….

ignore.dict

多少钱

时刻表

?

….

编写query解析代码,思路如下:

1.先使用pattern对整个query字符串进行匹配,匹配命中的可以是使用“term.dict词槽(包含)+杂志词(忽略)”组成的任意组合。匹配规则成功时,记录匹配term的key和value,例如:“[{from:北京,link:飞,to:亚龙湾,keyword:航班},{…},..]”,命中的pattern可以是多个,都记录下来。

2.对所有匹配成功的term value执行同义词转换,转换结果为:“[{from:北京,link:飞,to:三亚,keyword:航班},{…},..]”

3.扩展:还可以加上地域扩展,比如用户搜“限行”,我们自动加上他的ip所在城市“北京”,这样就能在下一步调出北京限行数据。

 

三、召回判定:从数据中检索对应数据并返回展示

有了第一步的da分类判定”10001″、第二步的query解析结果“[{from:北京,link:飞,to:三亚,keyword:航班},{…},..]”,接下来就可以进行数据查询。

通常情况下,不同分类的数据会分开存储,所以我们通过da分类”10001″到对应的数据库中,查询from=北京,to=三亚的数据,如果能调出数据,认为这个分类召回,调出并显示数据即可。如果da识别多个分类都被调出数据,再根据分类权重+分类点击权重+分类停留时长等策略控制分类的展示顺序。

在数据存贮上,简单检索条件的数据,数据存储建议用kv数据库+cache来实现,比如上例中,kv的key可以用”10001_北京_三亚”,这样检索性能相对较好;

有些复杂的场景,比如“2015款jeep指南者2.0t4驱豪华版报价”,用户只想看2015款+jeep+指南者+2.0t+4驱+豪华版的报价,用户的搜索query可能甚至是大于8个字段的复合检索,那么简单的key或普通的关系型数据库都是无法满足的,这时候需要自己实现一个索引存储+kv数据存储的机制,比如数据在建库时,还是以kv的形式存储,但是在存储前,根据检索的pattern配置,为检索字段生成索引数据,存入索引库,索引库中记录所有pattern匹配的数据index及对应kv存储的key,当检索时,就能直接从索引库调出符合索引的kv key,再拿key从kv中调出数据,这样就能以非常好的性能进行多条件检索了。在压力达到一定规模时,索引库和kv再加层cache,性能数据很不错。

这篇文章重点讲解了基于词槽的简单query匹配方法,适合搜索query不定,但对不同query分类有特定业务逻辑的场景。

yan 2016.8.3 0:20

欢迎关注下方“非著名资深码农“公众号进行交流~

发表评论

邮箱地址不会被公开。