- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在考虑某天我可能想要构建的各种应用程序的设计时,在某些情况下,我需要根据它们是否匹配用户提供的大量全文搜索查询。
此问题的一个简单示例是 Twitter 流式搜索等工具的实现:给定每秒数千条新推文,有效地仅选择其搜索查询可能与传入推文匹配的流式订阅者。
问题的陈述类似于“反向全文搜索”,其中全文是查询,搜索结果是与该文本匹配的搜索查询。
对于单个术语查询,实现是显而易见的:简单地标记传入文档,然后搜索术语映射->(订阅者列表),但是当 bool 查询成为可能时,事情变得更加困难。事实上,这个问题比全文搜索更普遍,但在那种情况下最容易理解。还有许多其他示例,其中大量 bool 项需要以某种方式组合以优化评估它们的成本。
例如,假设有 3 个搜索订阅:
一种可能是将查询解析成一棵树,然后访问每个节点,提取术语,并使用“术语映射”方法,但是这需要针对每个术语的传入文档重新评估订阅者查询.如果有足够的订阅者,这将很快开始变慢。
相反,我想知道是否有一种有据可查的方法可以将查询重写为单个查询,其中结果可以被评估一次,并且树节点用完全或几乎肯定已知的订户查询列表进行注释匹配树中指向该点的任何文档。
例如,上面的查询可能会被重写,以便存在 term->(query tree) 的映射,例如:
Google -> (分析[2]
玻璃 [1,3])
推特 -> ([3])
是否有任何现有的公开记录的系统可以执行类似的操作?理想情况下,该解决方案将允许逐步添加和删除订阅者,而无需执行一些昂贵的步骤来重写整个结构。
最佳答案
执行此操作的一种方法是使用将术语映射到查询的简单字典。所以给出这四个查询:
Query1: Google AND Glass
Query2: Google AND Analytics
Query3: ((Glass AND Google) NOT Knol) OR Twitter
Query4: Quick AND red AND fox
您构建了一个字典,以术语为关键字:
Google: Query1, Query2, Query3
Glass: Query1, Query3
Analytics: Query2
Knol: Query3
Twitter: Query3
Quick: Query4
red: Query4
fox: Query4
现在,考虑像“The red glass on the knol is from Google”这样的句子。
解析每个单词并在字典中查找。对于字典中的每个单词,将其查询列表添加到您的主查询列表中。此外,对于在字典中找到的每个单词,将其添加到相关单词的哈希表中。在此步骤结束时,您将拥有两个结构:要检查的查询列表和相关词列表:
Queries list: Query1, Query2, Query3, Query4
Relevant words: Google, Glass, Knol, red
现在是处理每个查询的问题,检查单词是否在相关单词列表中。
例如,对于查询 1,您将检查相关词列表是否包含 Google 和 Glass。
这个的复杂性还算不错。您对文本中每个已解析的词进行 O(1) 查找。对于在解析阶段识别的每个查询,您对相关单词哈希表进行了一些 N、O(1) 次查找。进行 bool 值计算时涉及的逻辑非常少,但大多数查询都是简单的“所有词”或“任何词”类型的查询(即“this AND that”或“this OR that”)。
此模型的好处在于它很容易分包给多个处理器。您可以在单个线程中解析单词,将它们推送到并发队列。多个线程为队列服务,进行查找并构建自己的需要检查的查询列表。完成所有这些查找后,您可以合并来自多个线程的查询列表,并再次将它们放在多个线程可以服务的并发队列中。
假设您有 100 万个查询,平均每个查询五个词(这可能是一个很大的平均值)。这里绝对最坏的情况是某些文本至少包含来自每个查询的一个词。因此,您有一个包含一百万个查询的列表要检查第 2 步。最坏的情况是 500 万个字典查找。
此算法的第一遍是 O(n),其中 n
是传入文本中的单词数。这将创建一个包含 k
查询的列表。第二遍是 O(km),其中 m
是每个查询的平均单词数。
这种方法的优点在于它的简单性,并且它对于中等数量的查询表现良好,具体取决于您输入的文本的大小。有一种可能更快的方法,但涉及更多。
您无需构建将术语映射到查询的字典,而是使用修改后的 Aho-Corasick 字符串搜索算法,该算法非常类似于 Unix fgrep
程序用于在单个文件中匹配多个正则表达式的算法传递文本。其中的细节超出了我在这里的简短说明中解释的能力。您可能想找到一篇名为“并行模式匹配和 fgrep”的旧 Dr. Dobb 期刊文章,我记得这篇文章对这是如何完成的有一个相当好的解释。 (快速搜索没有找到文章正文,但你可能运气更好。)你还想阅读原始的 Aho-Corasick 论文:Efficient String Matching: an Aid to Bibliographic Search .这讨论了并行模式匹配文字字符串,但基本思想适用于匹配正则表达式或 bool 搜索查询。
关于algorithm - 索引全文搜索查询以实现高效扇出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24004361/
我在使用带有 vector STL 的迭代器时遇到了这个错误。 代码:- #include #include void print_vec(std::vector vec) { auto
JAVA:两个引用“p”&&“pp”之间有区别吗? PrintStream p = new PrintStream(System.out); p.println("lol");
我尝试从主分支中拉出,但收到错误消息: $ git --no-optional-locks -c color.branch=false -c color.diff=false -c color.sta
我面临着一个让我抓狂的问题! 我有一个函数,这个: void load_weapons3(t_env *e, char *name, int x, t_weapon *w) { char
我正在尝试使用 CUDA 中的最小值、最大值、总和和平均值实现并行归约。 这是我目前的主要代码片段。 int main() { const auto count = 8; const
我知道 double free 或 corruption 错误通常是对 big 3 的违规,但在这种情况下,我找不到违规发生的地方。我有一个复制构造函数、析构函数和赋值运算符,适用于任何处理指针的东西
GTK+ 中的“focus”和“focus-in(out)-event”信号有什么区别?哪个先发射?它们与键盘(TAB)和鼠标点击有什么关系。他们互相依赖吗? 我问这个是因为我想在顶层窗口中跟踪当前聚
*** glibc detected *** /home/ghoshs/workspace/Simulator/Debug/Simulator: double free or corruption (
#include #include #include #include using namespace std; #define MAX_WEIGHT 1000000 class Set {
我在服务器上有两个分支一个叫 R2 的分支和一个叫 DEV 的分支我无意中登录了错误的服务器,进入了存储库并执行了GIT pull 源开发但是存储库在 R2 上。所以我意识到我的错误然后尝试通过做一个
我有一个包含循环的大约 1000 个顶点和 3000 个边的有向图。 我试图从给定的顶点找到所有下游(出)路径。 使用以下 Gremlin 查询时 g.V(45712).repeat(out().si
使用 Delphi XE 2 我试图确定缩放方向以将缩放效果应用于图像(TImage),但没有找到执行此操作的函数,并且图像的 OnGesture 事件中的 EventInfo 属性没有此信息. 我见
我正在尝试创建一个 Zoom_image 函数,它使用离散傅里叶变换来缩放灰度图像。如果图像大小小于或等于 4*4 但大小增加,我包含的代码可以工作。它给出“双重释放或损坏(出)中止(核心转储)”错误
当我执行 popAll 函数时,出现以下错误: 双重释放或腐败(出)中止(核心转储) 我想我已经将错误来源缩小到了这个函数。 IntegerStack 是我制作的一个简单的 ADT,其中包含一个名为
我有网络开发背景,我正在尝试创建类似于 this technique 的东西适用于 iOS(使用 Cocoa/Obj C)。我在谷歌搜索资源时遇到了很多困难,因为 iOS 中的“视差”往往指的是 iO
我想实现一个 faceted search对于我的一个项目。我正在使用 PHP5、Mysql 和 Symfony 1.4。显然社区指向Apache Solr这似乎正是我想要完成的。 问题是该网站将在不
我知道有 questions floating around当您没有提供明确的分支名称时,关于来自特定分支的 git pull,但是我想知道即使用户确实指定了不同的分支,是否也可以强制 pull 分支
我正在尝试将我的更改推送到 NAS 上的存储库。它以我无法理解的方式失败。 documentation声明默认情况下 push 仅适用于快进更新。很公平。所以我做了一个 git pull(我的 Rem
我刚开始使用 Oracle 的 Coherence 缓存,我注意到这一点:如果我在缓存中放入一个 ConcurrentHashMap 对象,当我检索它时,我可以看到它被转换为一个普通的 HashMap
我尝试创建一个连接到数据库的线程,从那里获取一些数据并打印到控制台。问题是当该线程完成时抛出异常: 双重免费或腐败(出局)中止(核心转储) 我尝试使用 sqlite3 和 pthread,但这两个并不
我是一名优秀的程序员,十分优秀!