Google app engine GAE和x27的解决办法;s 30子查询限制

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)个来源(卫报、泰晤士报等)的列表中选择他们最喜欢的新闻来源。我有一个包含索引属性“source”的新闻实体,我正在寻找一种方法,它可以让我绕过appengine对30个子查询的限制,而appengine禁止我使用IN和EQUALS过滤器来获取属于一个大来源列表的所有新闻

这个限制有什么解决办法吗


感谢您提供了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以添加此项。