GAE游标不使用IN进行查询,解决方法是什么?

时间:2013-11-11 22:27:26

标签: google-app-engine google-cloud-datastore objectify

我正在尝试对GAE的数据存储执行相当复杂的查询,基本上,订阅者可以订阅来自特定城镇或任何城镇(*),特定国家或任何国家(*)的新闻,具体...或任何......(*)

现在,当我想通知订阅者有关ZA的新闻时,我需要找到所有匹配country = ZA的用户以及匹配country = *的用户以及其他字段的用户。

Query<Subscriber> query = ofy().load().type(Subscriber.class);

    query  = query.filter("searchCategory IN", Arrays.asList(new String[]{"*", category}));
    query = query.filter("searchCity IN", Arrays.asList(new String[]{"*", city}));
    query = query.filter("searchSuburb IN", Arrays.asList(new String[]{"*", suburb}));
    query = query.filter("searchTown IN", Arrays.asList(new String[]{"*", town}));
    query = query.filter("searchProvince IN", Arrays.asList(new String[]{"*", province}));
    query = query.filter("searchCountry IN", Arrays.asList(new String[]{"*", country}));
    query = query.limit(100);

    QueryResultIterator<Subscriber> iterator = query.iterator();
    while (iterator.hasNext()) {
        Subscriber subscriber = iterator.next();
        System.out.println(iterator.getCursor().toWebSafeString()); // exception here
    }

我正在使用任务队列一次通知大量订阅者,一次100个(根据查询结果在20k到2M之间),游标似乎是分解大量结果的合理方式在可管理的块中...直到我运行应用程序并获得一个Null Pointer Exception试图获取游标 - 结果是在使用IN语句时不支持游标。

  

因为NOT_EQUAL和IN运算符是用多个实现的   查询,使用它们的查询不支持游标,也不支持游标   使用CompositeFilterOperator.or构造的复合查询   方法

在这种情况下看到我不能使用游标的替代方法是什么?

2 个答案:

答案 0 :(得分:2)

根据文档

,我认为你可以使用游标
  

某些NDB查询不支持查询游标,但您可以修复它们。   如果查询使用IN,OR或!=,则查询结果将无法使用   游标除非按键排序。如果申请没有订购   按键结果并调用fetch_page(),它得到一个BadArgumentError。如果   User.query(User.name.IN([ '乔',   'Jane']))。order(User.name).fetch_page(N)出错,将其更改为   User.query(User.name.IN(['Joe','Jane']))。order(User.name,User.key).fetch_page(N)

我建议您更快地切换到NDB并自动缓存

答案 1 :(得分:1)

一种选择是仅使用equals独立运行每个查询。这将允许您只获取一些条目,但是除了光标之外,您还必须记住正在运行的查询。这也不会为您处理重复数据删除 - 如果您发送通知,这可能是一个交易破坏者。

您应该考虑查看prospective search API。这是一个实验性功能,但它完全符合您的要求。

基本思路是,为每个用户指定他们的订阅查询(例如searchCountry=NZ),然后当您处理新闻文章并将其发送到预期搜索API 时,它可以为您提供与该文章匹配的所有订阅(查询)。