我正在使用带有Objectify的GAE/Java,并且我正在尝试找到检查数据存储区中是否存在给定对象的最快方法.我在做什么,现在是.get(key)有@Cached,但无论哪种方式,仍然检索整个对象,这是不必要的.
关于如何使用索引执行此操作的任何想法只会命中?我还想到了一个只有密钥的查询,但我看到(在系统状态仪表板上)延迟远远超过了get.
你能找到一个关于在Google App Engine Objectify世界中实现良好分页的好教程或文档吗?
我找到了一些帖子:http: //groups.google.com/group/objectify-appengine/browse_thread/thread/b640b5d377b620b4
但似乎没有什么能帮助我.有某种LIMIT查询吗?
我有一个用Java编写的GAE项目,我对HRD和一个我不确定如何解决的问题有一些想法.
基本上我的系统中有用户.用户由用户标识,用户名,电子邮件和密码组成.每次我创建一个新用户时,我想检查是否已经有一个用户具有相同的用户ID(应该永远不会发生),用户名或电子邮件.
用户标识是关键,因此我认为使用此标准将是一致的.但是,当我进行查询(并使用过滤器)查找具有相同用户名或电子邮件的可能用户时,我无法确定结果是否一致.因此,如果有人在几秒钟之前创建了具有相同用户名或电子邮件的用户,我可能无法通过查询找到它.我知道祖先习惯于解决这个问题,但如果我没有用于查询的祖先呢?用户没有父母.
我很高兴听到您对此的看法,以及在这些情况下被认为是最佳做法.如果改变了什么,我正在使用Objectify for GAE.
我有这个类,我想使用Objectify持久化,这个类将表示大于1MB的数据,因此有一个Blob对象列表,它表示存储的字节数组的片段,其大小小于1MB:
@Entity
public class BigBlob {
@Id
private Long id;
public static final int FRAGMENT_LIMIT = 777 * 1024;
@Serialized
private List<Blob> fragments = new ArrayList<Blob>();
...
}
Run Code Online (Sandbox Code Playgroud)
然而,"片段"是@Serialized,它将使这个BigBlob类/对象的大小大于1MB.
导致此错误:
com.google.apphosting.api.ApiProxy$RequestTooLargeException: The request to API call datastore_v3.Put() was too large.
Run Code Online (Sandbox Code Playgroud)
如果我使用@Embedded注释,我会收到此错误:
Cannot place array or collection properties inside @Embedded arrays or collections
Run Code Online (Sandbox Code Playgroud)
如何确保"片段"作为单独的实体存储?
顺便说一下,我已经有了字节分块逻辑,它会切断整个字节数组并将片段放入其中List,Blob因此这个问题与如何切割字节无关.
我想知道的更多是坚持不懈的一面.
我正在开发一个关于Appengine和Android的应用程序,并计划将API Cloud Endpoints用于API和GCM,以实现云与移动之间的通信.我原本打算使用Objectify进行数据持久化,但我想知道是否会遇到意外的麻烦 - 特别是使用不同的注释或其他要求.有没有人有任何可以警告我的经验?
boolean r = ofy().transact(new Work<Boolean>() {
@Override
public Boolean run() {
Visit visit = ofy().load().type(Visit.class)
.filter(Visit.USER_ID, userID)
.filter(Visit.VENUE_ID, venueID).first().get();
if (visit == null)
return false;
visit.setLastRequestDate(new Date(timestamp));
ofy().save().entity(visit).now();
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
我明白了
java.lang.IllegalArgumentException:在事务内只允许祖先查询.
对于有get()电话的线路.
为什么?我只是Visit在这个交易中查询实体.我在一个事务中这样做,因为我希望所有这些都作为原子操作执行.
java google-app-engine transactions objectify google-cloud-datastore
目前,我有一些抽象的模型类,它们具有其他具体模型的共同行为.例如,抽象的SearchableModel.class可能会被其他具体模型继承.
使用Objectify时,我想注释SearchableModel类,因为它需要持久化它自己的字段.但是,我对进行任何类型的多态查询都不感兴趣,我不想在数据存储区中使用任何类型的"SearchableModel"实体,只需要继承自SearchableModel的具体类.我应该如何处理@ Entity/@ EntitySubClass注释?
如果我使用@Entity注释抽象类和具体类,并且持久化/加载具体类的实例,它是否会按预期工作?
我知道我可以自己测试一下,但是,我还没有设置客观化.我仍在试图弄清楚它如何与我当前的模型一起使用.
关于如何组织这种依赖性的任何其他建议也受到赞赏.
谢谢.
我正在尝试TimerTask定期从Google App Engine的dataStore中删除条目.所以我建立了ServletContextListener一个Timer.
在里面contextInitialized,我已经注册了我的Objectify课程:
ObjectifyService.register(Person.class);
Run Code Online (Sandbox Code Playgroud)
但是,当任务实际运行时,它会抱怨没有设置API环境:
Exception in thread "Timer-0" java.lang.NullPointerException: No API environment is registered for this thread.
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:80)
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:90)
at com.google.appengine.api.datastore.Query.<init>(Query.java:214)
at com.google.appengine.api.datastore.Query.<init>(Query.java:143)
at com.googlecode.objectify.impl.cmd.QueryImpl.<init>(QueryImpl.java:72)
at com.googlecode.objectify.impl.cmd.LoadTypeImpl.createQuery(LoadTypeImpl.java:50)
at com.googlecode.objectify.impl.cmd.LoadTypeImpl.filter(LoadTypeImpl.java:58)
at myApp.MyServletContextListener$MyTask.run(MyServletContextListener.java:58)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?我已经尝试更改注册该类的行,ObjectifyService.factory().register(Person.class);但它似乎没有帮助.
java google-app-engine scheduled-tasks objectify servletcontextlistener
事实证明,检索存储内存缓存的低级数据存储实体非常缓慢.由于objectify将实体缓存为低级数据存储区实体类型,因此当使用objectify从memcache中获取许多实体时,这会导致性能不佳.
真正的问题是为什么从memcache反序列化实体类型的速度慢?我整理了一个示例项目来演示从memcache与普通字符串或简单Map中检索实体的差异.
这是代码:
https://github.com/aleemstreak/perftest或相关文件:https://github.com/aleemstreak/perftest/blob/master/src/com/rewardly/perftest/PerftestServlet.java
此外,我部署了它,因此您可以看到它在生产中有多大差异:aleemsandbox.appspot.com/perftest.它是一个天真的探测器,但它确实表现出巨大的性能差异.刷新页面几次以查看差异.这是一些示例输出:
Storing String Data Test
-------------------------
generateData: 0ms
storeData: 10ms
fetchData: 9ms
Storing Map Data Test
-------------------------
generateData: 0ms
storeData: 21ms
fetchData: 92ms
Storing Entity Data Test
-------------------------
generateData: 69ms
storeData: 24ms
fetchData: 792ms
Run Code Online (Sandbox Code Playgroud)
第一部分显示了在memcache中存储1000个字符串然后立即获取它所需的时间.下一个示例对1000个Map对象执行相同操作,最后一个示例存储并检索1000个低级实体类型.您可以看到检索实体类型的时间增加.
任何想法为什么实体可能很慢从memcache反序列化?
更新1
根据其中一个答案中的建议,我还记录了存储在memcache中的对象的累积大小,结果没有打印出来.我还添加了另一个测试用例 - 而不是直接存储实体,而是首先将Entity序列化为byte [],然后将其存储在memcache中.结果如下:
StringBenchmark
----------------
Average Fetch Time: 40.16ms
Fetch Size: 24.41KB
MapBenchmark
----------------
Average Fetch Time: 27.36ms
Fetch Size: 102.54KB
EntityBenchmark
----------------
Average Fetch Time: 1029.88ms
Fetch Size: 463.87KB
EntityPreSerializedBenchmark
----------------
Average Fetch …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用带有Objectify和Google App Engine的光标来返回数据和光标的子集,这样我就可以在用户准备好时检索更多数据.我在这里找到了一个看起来完全像我需要的例子,但我不知道如何返回最终列表和光标.这是我的代码:
@ApiMethod(name = "listIconThemeCursor") //https://code.google.com/p/objectify-appengine/wiki/Queries#Cursors
public CollectionResponse<IconTheme> listIconThemeCursor(@Named("cursor") String cursorStr) {
Query<IconTheme> query = ofy().load().type(IconTheme.class).limit(10);
if (cursorStr != null ) {
query.startAt(Cursor.fromWebSafeString(cursorStr));
}
List<IconTheme> result = new ArrayList<IconTheme>();
int count = 0;
QueryResultIterator<IconTheme> iterator = query.iterator();
while (iterator.hasNext()) {
IconTheme theme = iterator.next();
result.add(theme);
count++;
}
Cursor cursor = iterator.getCursor();
String encodeCursor = cursor.toWebSafeString();
return serial(tClass, result, encodeCursor);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是从先前的端点修改的,在该端点中我返回了所有数据的CollectionResponse.我的数据集足够大,不再实用.基本上,我不知道用户的'serial(tClass,result,encodeCursor)函数是什么让它返回给用户.
这里有另一个例子,但似乎也没有回答我的问题.