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

时间:2015-10-04 21:51:20

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

鉴于以下两个表,如何在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;
  …
}

请注意,我在结果中查找的所有内容都是authorIds列表,如

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

英文版可能有点令人困惑,但这里有:我试图让30位最近出版书籍的作者。假设是每个作者都写了很多书。由于每本书都有出版日期,我想知道最近活跃的30位作者&#34;最近&#34;。如果你发现这种自然语言解释分散注意力,那么就忽略它:SQL说得好。

2 个答案:

答案 0 :(得分:2)

@stickfigure通常是客观化的专家,但他的反应有点令人费解。我的印象是你可以使用

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();
  }

答案 1 :(得分:1)

您无法将此作为使用GAE数据存储区的即席查询。解决此特定问题的一般建议方法是保存索引的&#34; lastPlublishDate&#34;作者实体上的属性并保持更新。然后,您可以通过简单的订单查询回答问题。

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