编程语言
首页 > 编程语言> > python – 在GAE中组合文本搜索和查询过滤器

python – 在GAE中组合文本搜索和查询过滤器

作者:互联网

我正在编写一个基于GAE的应用程序,它应该允许用户通过它们的几个属性来过滤项目.项目存储为NDB实体.一些道具可以通过标准查询过滤器进行匹配,但有些道具需要对整个事物进行“完整”(子串)文本搜索才有意义.另外,需要一些合理的排序.最好用以下设计的例子说明:

class Product(ndb.Model) :
  manufacturer = ndb.StringProperty()
  model = ndb.StringProperty()
  rating = ndb.IntegerProperty(choices = [1, 2, 3, 4])
  features = ndb.StringProperty(repeated = True, choices = ['feature_1', 'feature_2'])
  is_very_expensive = ndb.BooleanProperty()
  categories = ndb.KeyProperty(kind = Category, repeated = True)

产品实体都具有与其“容器”相同的祖先.产品可以属于一个或多个类别,后者形成树.

现在,用户应该能够:

>通过选择一个类别缩小产品(单个就足够了)
>通过指定最小评级和所需功能来过滤它们
>仅查看非常昂贵的产品或非(或查看全部)产品
>通过模型和/或制造商字段中的一段文本搜索产品
>订购最终清单,例如.按型号名称(选择订购的能力是理想的).

所有这些同时,即.在提供搜索词时,应无缝应用过滤器和排序.

问题是:如何使用GAE以performat方式实现此类功能?

数据库中将有数十万甚至数百万的产品. Search API与NDB查询一起使用时,问题是过滤搜索结果并可能对它们进行排序.

我一直在想的两个解决方案:

>将重复的StringProperty添加到Product模型,该模型将包含来自制造商和模型字段的所有可搜索的字符串(或至少前缀).它很容易,但它很有效,但我非常关心性能.在我的实验中,我为每个“产品”平均获得了40-50个可搜索的单词前缀.
>使用高级搜索查询专门为任务使用Search API.例如.我可以将产品的类别(作为ID或路径)存储在单独的文档字段中,并使用此字段来获取属于给定类别的产品.它可能已经完成,但我在这里关注的是10,000个搜索结果和各种使用限制/配额的限制.我也不确定结果的排序.

还有其他方法吗?

解决方法:

我强烈建议不要使用GAE.我知道这可能不是你想听到的,但它与你的用例不相符,并提供了我认为你想从产品搜索中获得的灵活性.听起来你真正想要的是接近faceted search的东西.

以下是GAE不匹配的原因:

>如果您使用NDB,您将很快遇到索引爆炸的情况,否则可能会因Zig-zag查询而导致性能严重下降. This article尝试为你正在做的事情做一个案例,但在实践中我们发现它不能在我的日常工作中扩展到小数据集/少数字段之外.你引入其他过滤器的顺序越多,这将给你带来的问题就越多,更不用说你是否开始需要多种不等式.
>与其他产品相比,GAE全文搜索速度缓慢且有限.查询语言本身并不是那么成熟和灵活的IMO.它的成本/配额也不是很友好.你提到你关心配额,搜索很容易通过它们吃.
>子字符串方法会使您保存的每条记录的大小膨胀. Django non-rel有一个完全正确的indexer package,并不是很漂亮.不确定你是否使用Django,但无论如何你可以调整代码,因为它是开源的.膨胀记录大小是不好的,因为除非您只使用投影查询或密钥,否则您将通过网络发回大量不必要的数据.

相反,我建议您将数据推送到针对这些类型的查询进行了更优化的数据存储.以下是架构的示例大纲:

>使用App Engine在Google Compute Engine上搜索服务器以减少延迟.不确定是否有办法让事情在同一个地理位置,但我怀疑你在这里托管它比在亚马逊的延迟方面更好.显然你可能会失去一些速度,但它可能仍然比内置的GAE全文搜索更快.
>如果需要扩展群集,可以使用ElasticSearch.请注意,如果您执行此操作,则需要在Google计算引擎上正确设置多播. ElasticSearch为此提供了一个插件.
>根据数据量创建使用推送或拉取队列的后台进程,以更新搜索索引.频率取决于您需要数据的“新鲜度”.推送与拉动的决定将在很大程度上取决于您的音量,但我建议使用拉动队列,将专用服务器推送给您的搜索提供商.无论如何,您必须使用内置的全文搜索来执行此操作.
>创建一个地图缩减作业,将所有数据推送到搜索索引.这对于播种初始队列和定期“刷新”都很有用.

上面的缺点是,您将大大增加您执行的URL提取调用的次数,并且数据可能并不总是新鲜的.后者在大多数搜索情况下都是正常的,前者可能比内置全文搜索更便宜,具体取决于您的音量.如果数据很少发生变化,您可以执行诸如转储到Google云端存储之类的操作,然后以更便宜的方式导入.

标签:python,search,full-text-search,google-app-engine,app-engine-ndb
来源: https://codeday.me/bug/20190629/1322583.html