2

我是新来的。我正在为一个激光标签的地方写一个应用程序,我们有很多年龄的孩子来互相射击光束。我们正在制作一个高分屏幕,它将显示一天、一周和一个月的最佳分数。这个想法是,人们会为上榜感到自豪,而且每个月还会有一次奖品。

我陷入了按日期过滤的整个问题。

我基本上修改了经典的留言簿示例,使其可以添加分数和客户信息,并按分数对其进行排序。

    Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName);
    String fornavn = req.getParameter("fornavn");
    Integer score = Integer.parseInt(req.getParameter("score"));
    String email = req.getParameter("email");
    String tlf = req.getParameter("tlf");
    Date date = new Date();
    Entity highscore = new Entity("Greeting", guestbookKey);
    highscore.setProperty("date", date);
    highscore.setProperty("fornavn", fornavn);
    highscore.setProperty("score", score);
    highscore.setProperty("email", email);
    highscore.setProperty("tlf", tlf);

    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    datastore.put(highscore);

在 jsp 中有一个查询可以获取整体前 5 名。

Query query = new Query("Highscore", highscoreKey).addSort("score", Query.SortDirection.DESCENDING);
List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));

还有一个表单将用户输入发送到.java。关于我应该如何设置日期的任何提示?保存周 # 和月 # 并基于此查询?看起来很麻烦。

4

3 回答 3

1

据我所知,您的“HighScore”类型实际上是一种“Score”类型,可以跟踪所有分数。

与其查询周/月的高分,不如拥有一个在输入分数时更新的单个 HighScore 实体(与正常的“分数”实体分开)。每次输入新分数时,检查是否应更新高分。

您永远不需要花哨的查询,您只需要获取高分实体。

或者您可能希望每个月/周等都有一个单独的高分实体,这样您就可以跟踪历史记录。在这种情况下,您可能希望将周或月编码到实体键中,以便您可以轻松获得当前周/月的 HighScore。

于 2013-07-09T17:04:35.303 回答
1

对于像您这样的要求,您希望显示一天、一周、一个月等的高分,有两种可能的方法:

1,第一个选项是使用您当前存储日期和分数的模型。由于应用引擎只允许对 1 个属性进行不等式过滤,因此您需要在日期上应用不等式过滤器,然后找到 n 最高分数。但由于结果将首先针对具有不等式过滤器的属性进行排序,然后再针对任何其他属性进行排序,因此您不能仅对前 n 个条目进行提取以找到前 n 个条目,因为最高分数不需要连续排列。看到这个帖子更好地理解这一点。因此,您必须获取日期范围内的所有分数,然后在客户端对查询结果进行进一步排序以找到前 n 个。如果一周或一个月的总分数与 n 的值相比不会太高,这种方法是可以的。如果不是,这不是一个可扩展的选项。

2,第二种方法是重新设计您的模型,以便对分数进行排序,以便获得特定时期的前 n 个分数,您只需要获取前 n 个条目。这意味着即使分数数量非常大,该方法也适用。然后,这需要将您的日期转换为适合相等过滤,例如存储月份编号、周编号和日历年的每个条目。然后例如,如果您想查找第 3 个月的前 n 个分数,那么您可以查询month=3, sort by scores descending并获取前 n 个匹配条目。同样,您可以使用周数查询特定周。

于 2013-07-09T19:10:41.490 回答
0

这与另一个高分 SO 问题非常相似。我已经在下面复制/粘贴了我的答案。使用数据库查询接近这个解决方案可能会让您加入抱怨 GAE 的行列。您将使用自定义索引。您的查询可能会比每个请求所需的平均慢 10 毫秒。您将需要索引数千条甚至数百万条记录。这会花费你的钱——也许很多都是因为:数据存储(索引)和实例,因为你对可能是高度调用的处理程序函数的延迟很高。请换个思路。我的复制/粘贴不是特定于您的设置,但可以轻松扩展。我希望它可能会促使您考虑更低资源、更低成本的替代方案。一如既往……HTH。-史蒂夫

以前的高分答案:您可能需要考虑另一种方法。这是很多索引开销,这将导致您的成本更高,执行此功能的处理程序的响应时间要慢一个数量级,并且您将有时索引更新的最终一致性会影响此数据的维护. 如果您有一个繁忙的站点,您肯定不会对与此方法相关的延迟和成本感到满意。

有许多替代方法。您预期的每秒站点事务数会影响您的选择。这是一个非常简单的替代方案。使用 TextProperty 创建一个 ndb 实体。使用诸如 score_userid 之类的字符串对得分最高的条目进行序列化。通过将它们与唯一字符连接起来,将它们存储在文本字段中。当一个新的分数进来时,使用 get_by_id 来检索这个记录(ndb 会自动为你处理 memcaching)。将其拆分为一个数组。拆分数组的最后一个元素,并检查新分数。如果它小于分数,则删除它,并将新的 score_userid 字符串附加到数组中。对数组进行排序,加入它,然后 put() 新的 TextProperty。如果您愿意,您可以设置一天结束的 cron 来扫描您当天的分数,以检查您的过程是否受到两个分数几乎同时到达导致一个分数覆盖另一个分数的极小可能性的影响。HTH。-史蒂夫

上一个SO高分答案链接:

使用 objectify 过滤和排序的 GAE 数据存储查询

于 2013-07-10T01:34:22.773 回答