Google app engine GAE和x27的解决办法;s 30子查询限制
我正在编写一个新闻应用程序,我想让我的用户从一个包含数十(~60)个来源(卫报、泰晤士报等)的列表中选择他们最喜欢的新闻来源。我有一个包含索引属性“source”的新闻实体,我正在寻找一种方法,它可以让我绕过appengine对30个子查询的限制,而appengine禁止我使用IN和EQUALS过滤器来获取属于一个大来源列表的所有新闻 这个限制有什么解决办法吗Google app engine GAE和x27的解决办法;s 30子查询限制,google-app-engine,google-cloud-datastore,Google App Engine,Google Cloud Datastore,我正在编写一个新闻应用程序,我想让我的用户从一个包含数十(~60)个来源(卫报、泰晤士报等)的列表中选择他们最喜欢的新闻来源。我有一个包含索引属性“source”的新闻实体,我正在寻找一种方法,它可以让我绕过appengine对30个子查询的限制,而appengine禁止我使用IN和EQUALS过滤器来获取属于一个大来源列表的所有新闻 这个限制有什么解决办法吗 感谢您提供了60个源,如果用户想要其中的30个,您可以将交互分成两个查询(一个用于30个,第二个用于其余),然后自己合并结果。当然,这是
感谢您提供了60个源,如果用户想要其中的30个,您可以将交互分成两个查询(一个用于30个,第二个用于其余),然后自己合并结果。当然,这是有实际限制的,因为您不想以无限数量的查询结束,但这应该扩展到远远超过您当前的60个源,而不存在太多问题 例如,在Python中,要生成查询列表:
def many_source_queries(sources):
queries = []
for i in range(0, len(sources), 30):
queries.append(News.source.IN(sources[i:i+30]))
return queries
然后,要合并多个查询的结果,当然有很多方法,但简单的方法是将所有内容都提取到一个列表中,这相当简单:
def fetch_many_queries(queries):
return [x for q in queries for x in q.fetch()]
当然,您可以添加过滤器、排序(并对流执行heapq.merge
,以保持结果的顺序)等等。我只是在解决“30个子查询限制”
添加:这只会扩展到一个点(特别是在查询中所需的源数量方面)。例如,如果实体可以有(比如)600个不同的源,而一个查询需要300个,那么您将得到返回给您的数据存储的大约一半(如果每个源的新闻数量大致相同),并且为此目的进行10个单独的查询是没有意义的
正如我在上面所写的那样,“有一些实际的限制,因为你不想以无限数量的查询结束”。在检测到超过某个阈值N个源(商店内容的很大一部分)的查询时,我宁愿使用源过滤器进行单个查询,并在应用程序级别选择性地忽略具有“错误源”的实体
所以在这种情况下,我会采取不同的方法,例如:
import itertools as it
def supermany_source_queries(sources):
return News.query(), set(sources)
def next_up_to_n(n, news_query, sources_set):
def goodnews(news): return news.source in sources_set
while True:
page = list(it.islice(it.ifilter(goodnews, news_query), n))
if not page: break
yield page
这里,主线代码将首先调用
q, ss = supermany_source_queries(sources)
然后从q
使用任何准备准确的查询eq
。过滤和/或。可能需要排序,然后循环,例如
for onepage in next_up_to_n(pagesize, eq, ss):
deal_with_page(onepage)
当然,这可以通过几种不同的方式加以考虑(最好是使用自定义类,根据所请求的源的数量采取不同的策略),但我再次尝试强调总体思路,即…:而不是对数百个源使用大量单独的查询,不管怎样,当您要返回大部分数据存储时,请使用一个查询(因此,请自行获取所有数据存储,而不是(比如)其中的一半,这当然取决于其他筛选器和处理页面
中可能的提前终止),并在应用程序级别使用迭代和选择(使用itertools
&c)忽略实际上不感兴趣的实体。请记住,索引是昂贵的——它们占用大量空间并使写入成本成倍增加
我会使用不同的设计,而不是60个子查询(如果源列表增加到500,会发生什么情况?)我将使源属性未编制索引。然后我将加载所有最新新闻的列表并将其保存在Memcache中。如果您丢失了它,您可以随时重新加载它。您还可以在收到新闻时轻松将更多项目添加到此列表中。您还可以根据时间将此列表拆分为块
现在,当用户进行呼叫时,您可以轻松地在内存中筛选此列表。根据您的使用量,此设计将便宜数十倍或数千倍,并且工作速度更快。最大的区别是,您将不必为每个用户请求反复读取相同的实体,而只需读取一次即可满足数千个请求sts,然后您需要再次阅读它们。谢谢@Andrei在进入区域后,源列表可能会增长到数百个。我不确定您提出的设计是否适合我的应用程序的规格,如无限滚动和复杂过滤(属于特定来源的最受评价、观看和评论的新闻)我不想独自完成所有这些。此外,我已经实现了缓存层、服务器端和客户端,以最大限度地减少对数据存储的查询。实际上,这些要求使这种设计更具吸引力。只要在Memcache中保留最新的新闻列表,就可以避免使用搜索条件的唯一组合来查询数据库r每位用户。谢谢@alex该列表将来可能会增加到数百个源,您是否保持使用数百个过滤器查询数据存储的方法,是否有更好的方法用于此配置?@Hakim,没有,如果一个典型的查询需要(比如)300个源,则将其转换为对数据存储的10次点击会变得非常过分(重要的是实体中有多少个源,查询中有多少个源);正如我所写的,“有实际的限制,因为你不想以无限数量的查询结束”。当检测到超过某个阈值的N个源的查询时(存储内容的很大一部分)我宁愿只做一个查询,而不使用源过滤器,并在应用程序级别选择性地忽略具有“错误源”的实体)。嗯,我将编辑a以添加此项。