gpt4 book ai didi

google-app-engine - 带有光标的Google App Engine数据存储区查询不会迭代所有项

转载 作者:IT王子 更新时间:2023-10-29 01:59:25 26 4
gpt4 key购买 nike

在我的应用程序中,我有一个带有过滤器的数据存储区查询,例如:

datastore.NewQuery("sometype").Filter("SomeField<", 10)

我正在使用游标迭代结果的批次(例如在不同的任务中)。如果在迭代时更改 SomeField的值,则光标将不再在Google App引擎上工作(在devappserver上正常工作)。

我在这里有一个测试项目: https://github.com/fredr/appenginetest
在我的测试中,我运行了 /db,它将db设置为10个项,其值设置为0,然后运行 /run/2,以5个为一批,对值小于2的所有项进行迭代,并更新每个项的值至2。

我的本地devappserver上的结果(所有项目均已更新):

appengine上的结果(仅更新了五个项目):

难道我做错了什么?这是一个错误吗?还是这是预期的结果?
在文档中指出:

Cursors don't always work as expected with a query that uses an inequality filter or a sort order on a property with multiple values.

最佳答案

问题是游标的性质和实现。游标包含最后处理的实体(已编码)的键,因此,如果在执行查询之前将游标设置为查询,则数据存储区将跳转到由游标中编码的键所指定的实体,并从那一点。
让我们来看看你的情况
您的查询过滤器是Value<2。您遍历查询结果的实体,然后将Value属性更改(并保存)为2请注意,Value=2不满足过滤器Value<2
在下一次迭代(下一批)中,将显示一个光标,您可以正确应用该光标。因此,数据存储区执行查询时,它会跳到上一次迭代中处理的最后一个实体,并希望列出此之后的实体。但是光标指向的实体可能已经不满足过滤器;因为它的新值2的索引条目很可能已经被更新(非确定性行为-参见eventual consistency以获得适用于此处的更多详细信息,因为您没有使用Ancestor query来保证strongly consistent结果; time.Sleep()延迟只会增加这)。
因此,数据存储区看到最后处理的实体不满足过滤条件,并且不会再次搜索所有实体,但是报告说没有更多的实体与过滤条件匹配,因此不会再更新任何实体(也不会报告错误)。
建议:请勿同时使用游标,过滤器或对要更新的同一属性进行排序。
顺便一提:
您引用的Appengine文档中的部分:

Cursors don't always work as expected with a query that uses an inequality filter or a sort order on a property with multiple values.


这不是你的想法。这意味着:光标可能无法在具有多个值的 属性上正常工作,并且该属性要么包含在不等式过滤器中,要么用于对结果进行排序。
顺便说一句#2
在屏幕快照中,您正在使用SDK 1.9.17。最新的SDK版本是1.9.21。您应该对其进行更新,并始终使用最新的可用版本。
实现目标的替代方法
1)不要使用游标
如果记录很多,将无法一步一步更新所有实体,而假设您更新了300个实体。如果重复查询,则已更新的实体将不在再次执行同一查询的结果中,因为更新的Value=2不满足过滤器Value<2。只需重做查询+更新,直到查询没有结果。因为您的更改是idempotent,所以如果实体的索引条目的更新被延迟并且不会被查询多次返回,则不会造成任何损害。最好延迟下一个查询的执行,以最大程度地减少这种情况的发生(例如,在重做查询之间等待几秒钟)。
优点:很简单。您已经有了解决方案,只需要排除光标处理部分即可。
缺点:有些实体可能会多次更新(因此更改必须是idempotent)。同样,对实体执行的更改必须是将实体从下一个查询中排除的内容。
2)使用任务队列
您可以首先执行仅键查询,然后将更新推迟到使用任务。您可以创建一个任务,假设每个任务传递100个 key ,这些任务可以按 key 加载实体并进行更新。这样可以确保每个实体仅更新一次。由于涉及任务队列,此解决方案的延迟会稍大一些,但这在大多数情况下不是问题。
优点:没有重复的更新(因此更改可能不是idempotent)。即使要执行的更改不会将实体从下一个查询中排除(更通用),该方法仍然有效。
缺点:更高的复杂性。更大的延迟/延迟。
3)使用Map-Reduce
您可以使用map-reduce框架/实用程序对许多实体进行大规模并行处理。不知道它是否已经在Go中实现。
优点:并行执行,甚至可以处理数百万或数十亿个实体。如果实体数量较大,则速度要快得多。加上2)使用任务队列中列出的专家。
缺点:更高的复杂性。可能在Go中尚不可用。

关于google-app-engine - 带有光标的Google App Engine数据存储区查询不会迭代所有项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30503343/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com