使用 objectify 为应用引擎执行 DISTINCT 查询

Executing DISTINCT query with objectify for app engine

给定以下两个表,我如何 write/execute 在 objectify 中进行以下查询:

SELECT DISTINCT(authorId) FROM Book ORDER BY DATE DESCENDING LIMIT 30.

@Entity
Book{
  @Id
  private Long bookId;//auto generated
  private Key<Author> authorKey;
  private String title;
  private Date date;
  …
}

@Entity
Author{
  @Id
  private Long authorId;//auto generated
  private String name;
  …
}

请注意,我在结果中寻找的只是 authorId 列表,如

public List<Long> getActiveAuthors(){
  ...objectify query goes here
}

英文版可能有点混乱,但这里是这样的:我正在尝试获取最近出版书籍的 30 位作者。假设每个作者都写了很多书。而且由于每本书都有出版日期,所以我想知道活跃的 30 位作者 "recently"。如果您发现这种自然语言解释让您分心,请忽略它:SQL 说得很好。

您不能真正将此作为使用 GAE 数据存储的临时查询来执行。解决此特定问题的一般推荐方法是在作者实体上保存索引 "lastPlublishDate" 属性 并保持更新。然后你可以用一个简单的订单查询来回答问题。

但是,如果您正在为即席分析查询寻找更广泛的通用解决方案,最好的答案可能是将数据副本复制到外部索引(例如,云 SQL),使用任务队列。然后您可以提出任何您想要的问题,无论计算强度如何,都不会冒主数据存储被淹没的风险。

@stickfigure 通常是 objectify 方面的专家,但他的回答有点令人费解。我觉得你可以使用

List<Book> booksProjection = ofy().load().type(Book.class).project(“authorKey”).
distinct(true).order("-publicationDate").limit(30).list();

然后一旦你得到了 booksProjection,剩下的就是像提取 authorKeys 然后查询作者一样简单;这样你的最终答案就是

public static Collection<Author> getActiveAuthors() {

    List<Book> result = ofy().load().type(Book.class).project("AuthorKey").distinct(true).order("-publicationDate").limit(30).list();
    List<Key<Author>> AuthorKeys = new ArrayList<>(result.size());
    for(Book n: result){
      AuthorKeys.add(n.getAuthorKey());
    }
    return ofy().load().keys(AuthorKeys).values();
  }