如何在服务器上实现自动完成功能?

5
这个问题很简单。在Web应用程序的客户端中使自动完成变得美观是简单的,有很多插件可用。但是,在后端,在服务器端,最好的方法是什么?我不喜欢每次用户按键时都要访问数据库的想法。
我一直在考虑使用Sphinx或一些全文搜索引擎并行运行于您的网站之外。例如,如果我有一个PHP(高流量)网站,我可以创建一个并行的Python脚本来获取来自我的“自动完成文本框”的HTTP请求。然后,在客户端按键时,AJAX请求被指向该Python脚本,该脚本可以使用特殊策略。
您的做法是什么?
一些约定:
尽量避免访问数据库。我的意思是,执行SELECT * FROM foo WHERE bar LIKE "req%"这样的请求不是一个好的答案。它可能是一个好的策略,但我知道如何做到这一点。
复制数据可能是一个不错的选择。

你似乎对服务器端可用的语言和技术有一些未明确说明的假设。如果您能明确说明,那么给出一个清晰的回复会更容易些。 - bmargulies
候选字符串集有多大?用什么标准来对它们进行排名(即对每个人相同,每个用户或甚至每个请求的标准)? - Ian Mackinnon
@bmargulies 我正在努力专注于架构。但是,作为一个指南。"搜索框架"(例如Lucene、Sphinx、Memcache等)可以是任何可以安装在Linux服务器上的东西。然后,关于编程语言,如果它是一个广泛采用的框架,它将有相应的库,但可以考虑一些好的编程语言:Java、Python、PHP。 - santiagobasulto
@Ian Mackinnon 很好的问题。这是一个小数据集(例如网站的所有关键字),而且相对静态。不理解“排名标准”这个东西。 - santiagobasulto
@santiago,排名是指您如何为用户排序建议列表。例如,“按字母顺序”对所有用户都相同,“最近由此用户搜索的”是每个用户,每个请求排名的示例。 - Ian Mackinnon
@Ian 太好了!我没有想过那个。这是一个好主意。谢谢!! - santiagobasulto
2个回答

8
我确实同意您需要一些更好的解决方案。Apache solr具有“建议”功能,您可以很好地使用它。如果数据集很小,则将所有数据放入内存中,然后只需执行简单的循环即可。
在前端,我建议使用setTimeout()等待约200ms再触发ajax调用。如果在这200ms内触发了另一个按键,则取消上一个超时并启动另一个超时。这是一个非常干净的解决方案,不会在每个按键击中数据库。我过去使用过它,效果非常好。
这篇文章很好地解释了使用jquery的solr以及如何创建自动完成功能。http://www.mattweber.org/2009/05/02/solr-autosuggest-with-termscomponent-and-jquery/

这是我过去使用过的一篇文章:http://www.sematext.com/products/autocomplete/index.html - Amir Raminfar
非常非常棒(循环1000次)。非常感谢。我会看一下的。 - santiagobasulto

0

你在评论中说“这是一个小数据集”的关键词。因此,当用户开始在字段中输入时,让客户端请求整个列表可能是合适的,然后让JavaScript响应客户端输入的更改。

每个页面每个字段只有一个服务器请求(仅当用户在字段中输入时),并且您可以在服务器上缓存它,因此它很少需要访问数据库。

编辑:在服务器上进行缓存非常重要,因为列表对于每个请求和所有用户都是相同的,但更好的是,这意味着您可以通过在响应中使用适当的ExpiresEtag头来将列表缓存在客户端浏览器中。因此,用户可以获得无限的自动完成,只需进行一次(良好缓存的)服务器请求即可在整个浏览器缓存期间使用。


1
是的,我考虑过了。但那不具有可扩展性。我的意思是,如果将来发生了什么变化,我不能继续在客户端加载所有数据。无论如何还是谢谢。 - santiagobasulto
1
@santiago,尽管考虑可扩展性非常重要,但优化已知的现在比优化未知的未来更为合理 :) 另外,我认为它在一定程度上是可扩展的;如果列表变得足够大,请开始请求与第一个字母匹配的所有关键字,或者稍后是前两个字母等。鉴于每个请求的开销相当大,您可能会请求一些可观的可能性列表,而不是在用户暂停打字一瞬间时每次都访问服务器。 - Ian Mackinnon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接