一个请求的历史

图片

想象一下您从事新工作的第一天。 办公室位于完全陌生的Kurskaya地铁站区域。 午餐快到了。 您打开搜索应用程序,写上“ East on Kursk”,并获得可供选择的用餐选择。

“库尔斯克吃”请求的背后是什么?如何处理它以找到您真正需要的东西? 在本文中,我将告诉您2GIS搜索团队如何尽一切可能使用户的城市生活更加便利和舒适。

重要的是要了解搜索查询的文本只是冰山一角,只是用户直接与之交互的一小部分。 除文本外,搜索查询本身还包含许多其他数据。 它们包括有关用户位置,他看到的地图区域,他的收藏夹中的记录集以及有关搜索模式的信息的个性化信息。 例如,在地图上或建筑物中进行搜索,或者对路线进行搜索。 数据是良好搜索功能成功的关键。

我们非常注意我们的数据及其结构。 此外,我们将搜索算法称为2GIS结构搜索,因为它可以通过对我们的结构化数据进行有效而快速的搜索而变得更加敏锐。 我们专门准备搜索索引及其构建数据。 我不会赘述,我只能说数据的组织方式要足够简单以至于可以处理,可以被很好地压缩,而且最重要的是,它使我们即使在移动设备上也可以快速处理数据。

此外,搜索可以脱机工作,因此对搜索索引的速度和数量有特殊要求。 我们非常重视此功能-我们会不断压缩搜索索引,评估各种平台上的性能,并在特定搜索条件超出设置的时间限制时加快功能。 顺便说一句,我们可以吹嘘移动设备上2GIS中的普通搜索查询比应用程序根据结果绘制下拉列表要快。

在下面,我将揭开神秘面纱,涵盖我们搜索的魔力。 例如,我们采用上述请求“在库尔斯克吃” 。 考虑其处理的阶段以及每个阶段发生的情况。 所以走吧!



阶段1.解析


输入参数:请求“在Kursk上吃”

首先,我们需要解析请求文本。 这很重要,因为在解析之后,我们不能使用请求文本,而可以使用它所组成的标记集。 令牌是单个请求字。 在我们的情况下,我们将收到一组三个令牌: “吃”“上”“库尔斯克” 。 看起来一切都很简单,但细节在于魔鬼。 有时并不太明显:例如,在“ wi-fi”或“第二”查询中,我们必须了解我们应该完整地处理这种组合。

令牌本身包含有关单词文本,请求中的位置,单词后面是否存在分隔符以及单词某些特征的信息-字符的寄存器,无论单词是数字,序号,电话号码,地址还是其他数据。

第二阶段。字典搜索


输入参数:标记“ eat”“ on”“ Kursk”

图片

有了准备好的请求标记列表,我们就可以进入字典搜索的阶段,也就是进入针对每个标记从数据中找到单词形式列表的阶段。 单词形式是有关单词词根及其结尾的编码信息。

我们将字典搜索作为一种分析字典的算法提出,以图形的形式呈现。 其中的节点是字母或符号。 图由符号节点和这些节点之间的过渡组成。 绕过字典图的结果是,根据上一阶段传输的令牌,我们可以获得许多单词形式。 因此,我们尝试在字典中查找与请求中的下一个标记匹配的字符序列。 同时,众所周知,用户在键盘布局中会打错字,遗漏字母甚至会犯错误。 因此,在浏览字典时,我们会进行一些操作,以考虑可能的人为因素或尝试猜测一个人现在正在获得什么。 使用了字符链的各种转换:插入,替换,附加字符等。

结果,对于图中的每个请求令牌,我们提取了一组单词形式,其中包含有关单词的词根和结尾的信息,有关单词形式中的字符数的信息以及找到的估计值。 评估发现-评估发现的字符序列到所需序列的词汇距离的评估。 评估表示找到的字符串与请求令牌有多少不同。

因此,对于令牌,我们发现单词形式:

  • “ eat”的 13种形式:“ eat”,“ eat”,“ paese”,“ payot”,...
  • “ on”的 3种形式:“ na”,“ nu”,“ on”
  • “ Kursk”的 48种形式:“ Kursk”,“ Kursk”,“ Kursk”,“ Kursk”,“ Kurako”,...

接下来,根据评估结果过滤找到的单词形式。 它们中的最佳者,即尽可能接近查询中的单词,落入术语列表中。 术语我们是指形式和发现的估计。 另外,除了找到的单词形式外,还将使用形态规则添加的术语添加到列表中。 形态学处理的重要步骤是添加形态学评估。 事实是,在我们的搜索中,我们使用了强大的形态处理机制,不仅使我们能够从字典中查找相似的单词,而且根据自然语言的规则,更准确地根据含义而不是单词的相似性来查找用户真正感兴趣的内容。

因此,将为令牌创建术语:

  • “吃” :“吃”,“吃”,“吃”,“吃”,“吃”
  • “开” :“开”,“ na”,“ nu”
  • “库尔斯克” :“库尔斯克”,“库尔斯克”,“库尔斯克”,“库尔斯克”,“库尔斯克”

在此阶段,词典搜索结束。 我们已经处理了请求,并为每个令牌列出了需要进一步处理的条款列表。 这些术语包含有关它们所代表的单词的所有信息,并评估如何找到它们。

步骤3.查找数据条目


输入:针对请求的每个部分的一组术语

  • “吃” :“吃”,“吃”,“吃”,“吃”,“吃”
  • “开” :“开”,“ na”,“ nu”
  • “库尔斯克” :“库尔斯克”,“库尔斯克”,“库尔斯克”,“库尔斯克”,“库尔斯克”

从上一阶段接收到针对请求的每个部分的一组术语后,我们便开始通过索引进行搜索。 数据中的每个文档都有许多标题,并以反向索引编写,因此我们可以轻松地在代表组织,地址或任何其他文档的特定文档中找到所需术语的所有引用。

对于请求的每个部分以及这些部分的每个条款,我们正在寻找包含以条款编码的单词的文档。 因此,对于部分请求,将在所有术语中找到条目:

  • “吃” :18个条目
  • :4,304条目
  • 库尔斯克 :79个条目

显然,介词“ on”出现了很多次,因此落入了许多文档标题中,例如“外卖咖啡”,“ 控制台播放”,“机器注册”。 “饮食”“库尔斯克”也被重复使用。 第二个单词及其词在我们的数据中的出现频率比第一个单词高。


通过命中,我们考虑了搜索查询中的单词与特定文档中的单词的匹配。 这些匹配将保存在列表中,将在下一步中进行分析。 当添加匹配时,我们不仅会从该词中复制有关单词中的数据,而且还会计算出如何找到该单词的最佳估计。 换句话说,我们选择术语的形态学评估,或对术语在词典中的查找方式的评估,具体取决于哪个等级更接近请求令牌。

此阶段是开始搜索本身的序幕。 我们已经在特定文档中准备了一组匹配项,根据这些匹配项,以下算法将选择并评估需要提供给用户的内容。

阶段4:搜寻的核心


入口:命中清单

  • “吃” :18个条目
  • :4,304条目
  • 库尔斯克 :79个条目

实际上,我们实现中的命中列表是一个非常棘手的容器。 重要的是要了解,向其中添加匹配项时,会创建特殊节点,在其中记录匹配项本身,并链接到这些匹配项所在的文档。

因此,如下所示显示输入数据会更正确:
入口:文档节点的容器

  • document1:{hits,...}
  • document2:{hits,...}
  • document3:{hits,...}
  • document4:{hits,...}
  • ...

首先,搜索开始绕过文档树,每个节点将其发送到分析器,分析器评估来自此节点的文档是否适合作为进入输出的结果。 为了了解分析仪必须处理的体积,我将首先说该容器包含3000多个节点! 但是可以在爬网过程中添加节点,因此,实际上它的处理甚至更多。 毫不夸张地说,分析是搜索中最昂贵的部分,同时也是项目中最复杂,规模最大的功能之一。 但是,即使在移动设备上,它的运行速度也非常快。

阶段5.分析


输入: Document节点:{hits,...}


分析首先从节点获得标题列表。 标题是标题和属于此文档标题的命中列表。 这些标题将在第一阶段进行评估。 对于我们来说,找出每个标题的有用性很重要。 有用性可以是好,弱和垃圾。

对于每个标题,都选择了命中链中最好的-长度和词汇量最好的,由命中的相似性组成。 根据最佳链接,将对标题进行实用性评估。 为了确定该链的有用性,我们还使用了一种基于文档中单词出现频率的机制。 粗略地说,单词在文档中出现的频率越高,它的重要性就越大( TF-IDF )。 因此,如果链中包含文档标题中的一个重要单词而没有很大的形态差异(例如,数量或性别都很好),则我们认为标题很有用。 如果标题的命中完全覆盖了文档标题中的单词,则标题也可能很有用。

使用实用程序,所有标题均形成该节点的实用程序掩码。 该掩码使我们对被分析的节点覆盖的请求令牌有了一个概念。 借助它的帮助,我们在很大程度上决定了是否进一步分析该节点。

结果,我们不仅从索引中获得了一个文档,而且还提供了一组结构化数据,这些结构化数据表示潜在结果以及有关如何找到该结果的信息。

步骤6.评估


输入: Document节点:{hits,...}


根据实用程序掩码,我们将处理该节点,或立即进行下一个。 在许多已处理的节点中,我们积累了有关其总数的各种信息。 例如,许多节点标题,节点之间的关系以及其他一些数据。

接下来开始分析彼此互连的节点的标题。 实际上,许多节点被组合成一个节点图,我们对其进行评估。

从图节点的节点中,我们获得了排名标题的列表。 简而言之,我们从各种节点组成一个标题列表,其中,对于每个元素,我们还从所有参与节点的标题命中中添加一个估计值和一个因素组合。

评估-从字典搜索阶段开始,该结构包含有关查询中标题所涉及的单词数的信息以及有关如何找到和处理该单词的许多其他因素的信息。 重要的是,来自排名标题的这些成绩将参与最佳成绩的选择。 其中一些将被标记为已选择,并将有助于对用户看到的结果进行最终评估。

总体评估会提供结果信息,这对于排序整个输出至关重要。 它包含一些因素,例如查询中缺少单词。 该度量特征在于其结构信息未被节点覆盖的单词数量。

根据有关标题效用的信息,确定结果的清晰度。 清晰度可以是好,弱和坏。 并在已处理节点的所有选定标题的参与下进行计算。 所有这些数据都对结果的命运和发布顺序产生重大影响。

渐渐地,我们即将结束对节点的分析。 在节点最终离开分析器并成为潜在结果之前,我们还要进行一些其他指定操作。 例如,所选文档标题的兼容性。

经过分析器所有圆周的节点形成一个结果,其中包含有关所选标题和文档的信息。 结果可以很好地覆盖搜索查询,并将结果发送到后处理。

步骤7.后处理


输入:从节点构造的结果


分析器会在它们成为结果之前从索引中过滤掉许多记录。 但是,在分析过程中,可以评估并发送许多潜在结果进行处理。 为了仅按相关性顺序向用户显示最有用的选项,我们需要切断分析仪发现的最差的选项。

在上一步中,提到了对结果的总体评估。 总体评估使我们能够在后期处理阶段中截取最差的结果。 等级如下。 不覆盖任何请求令牌的结果显然要比完全覆盖用户请求的结果差。 清晰度较差的结果显然不如清晰度较好的结果。 后处理器累积有关传入结果的信息,并消除那些明显较差的结果。 其余的添加到列表中。

在向饥饿的用户提供有关网吧的信息之前,我们先进行最终处理-按相关性排序。 排序涉及许多因素,这些因素是在搜索的不同阶段进行计算和汇总的。 最终, “吃库尔斯克”的搜索结果超过500个结果。 他们中许多人以相同的方式被发现,因此具有相同的评级。 它们将根据用户受欢迎程度进行排序。



结论


我们收到了许多咖啡馆和餐馆的引渡,很高兴我们去吃晚饭。 我们很快就得到了所有结果。 我们甚至都不需要互联网连接。

该应用程序将搜索索引存储在设备上。 这样的方案为我们提供了优化数据压缩和处理速度的艰巨任务-毕竟,搜索应该可以在各种移动设备上快速进行! 但是,这是一个完全不同的故事。

今天,我试图打开我们搜索引擎的引擎盖,向我们展示如何帮助用户在城市中找到他们所需的东西,并快速便捷地进行操作。 我希望它能提供信息。

Source: https://habr.com/ru/post/zh-CN433696/


All Articles