0

我正在尝试对 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 之间),游标似乎是将大量结果分解为可管理块的合乎逻辑的方式...直到我运行应用程序并尝试获取游标时遇到空指针异常 - 结果表明使用 IN 语句时不支持游标。

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

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

4

2 回答 2

2

根据文档,我认为您可以使用游标

一些 NDB 查询不支持查询游标,但您可以修复它们。如果查询使用 IN、OR 或 !=,则查询结果将不适用于游标,除非按键排序。如果应用程序没有按键排序结果并调用 fetch_page(),则会收到 BadArgumentError。如果 User.query(User.name.IN(['Joe', 'Jane'])).order(User.name).fetch_page(N) 收到错误,将其更改为 User.query(User.name.IN (['Joe', 'Jane'])).order(User.name, User.key).fetch_page(N)

我建议您切换到 NDB,因为它更快并具有自动缓存

于 2013-11-12T07:36:28.873 回答
1

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

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

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

于 2013-11-12T06:56:09.527 回答