关于Facebook Graph Search的来源与背后架构的笔记
关于Facebook Graph Search的起源与背后架构的笔记
最近读了一些关于Facebook Graph Search的资料,整理如下。本人对语义搜索也很感兴趣,希望对你有帮助。
1 起源
Graph Search beta是Facebook于今年年初推出的一款搜索产品。与传统的搜索引擎不同,它基于的不是分散在网络上的网页,而是Facebook拥有的十亿用户及其产生海量数据的结构化的数据库。让用户仅通过自然语言描述就能在 Facebook 上搜出自己感兴趣的好友、找约会对象、找工作机会、找饭店等。这个被扎克伯格认为“酷毙了”的产品的创造者是一位前 Google 工程师,叫做 Lars Rasmussen。Rasmussen 同时也是 Google Maps 的创造者。 在2011年,Zark非常希望能够把 Facebook 上用户分享的大量内容进行结构化重构,让用户能够在此基础上进行更有意义的搜索。Zark让搜索项目组设计、构建一个新的搜索系统来重新构建对整个庞大的“社交图谱”的搜索。这个挑战性很大——与传统的基于关键词的文档搜索不同,Facebook拥有一个巨大的、有结构化的数据的数据库,使用传统的方法不一定能够达到要求。曾经,Zark与Lars商讨过构建特定领域的小一些的产品,比如求职搜索或者本地搜索。这些是有“前车之鉴”的产品,通过它们帮助我们来进一步达到野心更大的目标。但是,他们决定一个野心巨大的目标:构建一个统一的、结构化的、基于自然语言的方法来搜索整个社交图谱,并且是高度可扩展的。 经历了一年有余的探索与开发,Lars Rasmussen领导的项目组推出了Graph Search beta,允许部分用户使用,其实也是项目组希望能够在真实的用户身上做A/B测试,这种方式能够有效地终结 Facebook 内部很多纸上谈兵式的争论。
2 Graph Search的背后
Lars Rasmussen提到整个系统最大的两个挑战是:
(1)高扩展性的搜索索引,能够实时更新大量新的结点和连接。
(2)构建自然语言查询的解析器,能够精确理解用户的自然语言,转化成需要的查询语言。
2.1 索引构建
Facebook Graph Search的整体架构面临有两个巨大的挑战:
(1)有超过10亿的用户在使用Facebook,每个月他们要分享给朋友超过2.4张照片,建立起超一万亿个几千种类型的连接。每天用户都在创建海量的内容,Graph Search系统需要在这些内容生成后几秒钟内就做好索引。整个系统需要一个具有高扩展性、高效的索引系统。
(2)Facebook已经有很多代码在跑很多的服务。当时,搜索项目组负责维护三个独立的搜索系统,维护它们耗费了大量的时间,如果再建立起第四个系统,将是一个沉重的负担。
我们的系统不同于传统的基于关键词的搜索,我们需要结构化的搜索,同时,我们的系统需要从多余一次连接之外寻找答案。幸运的是,项目组发现了Unicorn[4],一个倒排索引系统。我们先使用它重新构建了现有搜索的倒排索引;然后,我们扩展了它已达到Graph Search的要求。
Unicorn是一个系统被开发用来帮助找到那些没有被直接连接的内容,比如朋友的朋友。这个系统使得在不对朋友的朋友的列表进行索引的条件下检索执行单一的查询就能得到朋友的朋友关系成为可能。它从社交图谱中根据与其他结点的边的关系来选择结点。传统的索引是由term到文档集的映射,在Unicorn中我们将term换成”社交图谱“中的连接。它接受一个s-expression语法的语言,在一次查询中完成多层次的图的遍历,返回查询结果。
Graph Search联合使用了Hive、Hadoop、HBase来定期地将数据库中存储的内容转化成倒排的“基本的”索引,然后我们向索引服务器发送消息来实时更新“基本的”索引。
另外,一方面是高扩展性的索引,另一方面,出于隐私保护的考虑,用户可以搜索到的一定是其他用户允许的而这个用户可以通过Facebook其他合理渠道获取的信息。比如,用户希望搜索“Facebook员工的图片(photos of facebook employees)”,其搜索结果的任意一张照片必须是照片的拥有者已经与搜索者分享的图片。并且在这些与搜索者分享过照片的人必须在Facebook工作。用户的查询愈复杂,需要做的工作越多。下面的查询构建也会说到这方面的内容。
目前,Graph Search还没有索引所有用户的帖子内容和评论内容,这将是巨大的工作量,也是未来的工作重点之一。
2.2 查询构建
Facebook Graph Search有三层的查询语言: (1)用户输入的自然语言。 (2)一种预先定义语法的语义语言。 (3)s-expression语法的语言来从倒排索引中检索出可能的结果。 我们用实例来解释整个过程。用户输入“my friends who live in Sydney,Austrilia(我住在澳大利亚悉尼的朋友)",系统的解析器主要有3个任务: (1)找到最匹配用户输入的查询,然后将它们展示在搜索框下面。 (2)找到查询中出现的实体名字或者人名对应的对象,比如上面例子中,Sydney,Austrilia会转化为110884905606108(悉尼的唯一id)。在查询”Philip Lee's photoes“中,系统需要找到谁是Philip Lee。首先,如果有歧义的话(有很多叫Philip Lee的),系统会根据一些准则确定,如拥有共同朋友最多的一个。这个其实在Facebook中已经有一个叫Typeahead的系统做这个。 (3)在用户点击了一个推荐的查询后,我们将它们转化成内部的查询语言。 首先,”my friends who live in Sydney,Austrilia“会转化为一种语义语言,如下: intersect(friend(me), residents(110884905606108)) 从URL可以看出来: https://www.facebook.com/search/110884905606108/residents/me/friends/intersect 然后,会被转化为s-expression语法的语言: (and friend:767560056 city_to_user:110884905606108) 其实,系统会将它重写若干次变成有时候会更复杂的查询来让检索更加高效。 这里分三个步骤: 1)从倒排索引中检索出候选的答案 2)从候选中过滤掉用户无法有途径得到的任何内容(之前提到的) 3)根据许多标准来排序过滤后的结果。这个是一个没有尽头的工作,是项目组将会持续改进的地方。 在搜索结果中,系统会给出每个结果出现在这里的原因,为什么它是个好结果。
3 使用neo4j构建简单的graph search
有篇博客[4]描述了如何使用图数据库neo4j和其查询语言Cypher构建Graph Search。它将自然语言转化为Cypher语言查询neo4j。它会先导入你Facebook账户的好友信息,然后可以进行查询。 你可以在这里尝试它:http://neographsearch.herokuapp.com/ 源码在GitHub上:https://github.com/maxdemarzi/neo_graph_search
References:
[1]I am the pointy-haired engineering director for Facebook's search team, AMA by Lars Rasmussen.
[2]http://www.lifehacker.com.au/2013/01/how-facebook-built-graph-search-unicorns-and-failed-interfaces/
[3]Under the Hood: Building Graph Search Beta,
https://www.facebook.com/notes/facebook-engineering/under-the-hood-building-graph-search-beta/10151240856103920
[4]Quora上的问答:What exactly is Facebook Unicorn?
http://www.quora.com/Graph-Databases/What-exactly-is-Facebook-Unicorn
[5]http://maxdemarzi.com/2013/01/28/facebook-graph-search-with-cypher-and-neo4j/
转自