Python 如何在GAE'中检索记录的最新版本;s的高复制数据存储?
我创建了一个REST服务,用于将iPhone中的数据同步到我们的GAE。 在一些情况下,我们会在同一天收到两个条目。我相信我在Python 如何在GAE'中检索记录的最新版本;s的高复制数据存储?,python,google-app-engine,google-cloud-datastore,Python,Google App Engine,Google Cloud Datastore,我创建了一个REST服务,用于将iPhone中的数据同步到我们的GAE。 在一些情况下,我们会在同一天收到两个条目。我相信我在记录类的设计中犯了一个错误,在尝试任何数据迁移之前,我想再次检查我的假设和可能的解决方案是否正确 首先,我检查所有传入的json_记录,如果它发现count==1,那么这意味着有一个现有条目需要更新(这就是它有时出错的地方!!!)。然后,它检查时间戳,并且仅当传入的时间戳更大时才更新它,否则它将忽略它 for json_record in json_records:
记录
类的设计中犯了一个错误,在尝试任何数据迁移之前,我想再次检查我的假设和可能的解决方案是否正确
首先,我检查所有传入的json_记录,如果它发现count==1,那么这意味着有一个现有条目需要更新(这就是它有时出错的地方!!!)。然后,它检查时间戳,并且仅当传入的时间戳更大时才更新它,否则它将忽略它
for json_record in json_records:
recordsdb = Record.query(Record.user == user.key, Record.record_date == date_parser.parse(json_record['record_date']))
if recordsdb.count() == 1:
rec = recordsdb.fetch(1)[0]
if rec.timestamp < json_record['timestamp']:
....
rec.put()
elif recordsdb.count() == 0:
new_record = Record(user=user.key,
record_date = date_parser.parse(json_record['record_date']),
notes = json_record['notes'],
timestamp = json_record['timestamp'])
new_record.put()
我认为,GAE/Highreplication数据存储可以确保您面前有最新数据的唯一方法是通过密钥检索数据
因此,如果这个假设是正确的,我应该首先用一个日期字符串作为键保存我的记录
jsondate = date_parser.parse(json_record['record_date']
new_record = Record(id = jsondate.strftime("%Y-%m-%d")
user=user.key,
record_date = jsondate),
notes = json_record['notes'],
timestamp = json_record['timestamp'])
new_record.put()
当我必须查询记录是否已经存在时,我会通过它的键获取它,如下所示:
jsondate = date_parser.parse(json_record['record_date']
record = ndb.Key('Record', jsondate.strftime("%Y-%m-%d")).get()
现在若记录为空,那个么我必须创建一个新记录。
如果记录!=空,那么我必须更新它
我的假设和解决方案正确吗?
如何使用日期字符串作为密钥迁移此数据
更新
我刚刚意识到我又犯了一个错误。我无法将记录设置为其日期字符串。因为每个用户可以有一天的记录,这会导致密钥重复
我相信解决这个问题的唯一办法是通过祖先/父母
,我仍在努力解决这个问题
更新2:
看看我是否理解Patrick的解决方案。如果没有道理,或者有更好的方法,请纠正我
我会在现有模型中添加一个is_fixed
标志:
class Record(ndb.Model)
user = ndb.KeyProperty(kind=User)
is_fixed = ndb.BooleanProperty()
...
然后,我会通过游标查询现有记录,然后删除它们:
q = Record.query()
q_forward = q.order(Record.key)
cursor = None
while True:
records, cursor, more = q_forward.fetch_page(100)
if not records:
break;
for record in records:
new_record = Record(parent=user.key, ... )
new_record.is_fixed = True
new_record.put()
//now delete the old ones, I wonder if this would be an issue:
for old in Record.query()
if not old.is_fixed:
old.delete()
因为您的查询总是按用户进行的,所以我建议让用户成为用户的祖先 正如您提到的,您遇到的问题是最终一致性的结果——您的查询不能保证有最新的结果。对于祖先查询,结果将是 需要注意的一个重要方面是,在实体组(单个祖先)中,每秒只能更新一次。因为每个用户只有一条记录,所以这似乎不是问题 您的代码实际上已全部设置为用户祖先:
new_record = Record(parent=user.key, # Here we say that the ancestor of the record is the user
record_date =date_parser.parse(json_record['record_date']),
notes = json_record['notes'],
timestamp = json_record['timestamp'])
现在您可以实际使用强一致性查询:
Record.query(ancestor == user.key, Record.record_date == date_parser.parse(json_record['record_date']))
但是,在更改现有记录的id时也会遇到同样的问题。将祖先添加到实体中实际上是在更改将祖先作为前缀的密钥。为了做到这一点,您必须遍历所有记录,并以其用户为祖先创建新记录。您可能可以使用查询来批量获取结果(使用以向前推进),或者如果您有大量数据,可能值得探索空部分的。和创建使用get\u或\u insert。除此之外,看起来不错。这报告说解决方案已应用,但并未真正解决问题。谢谢Patrick。这对我来说很清楚,但有一件事。我们有2721条记录,所以也许光标可以完成这项工作。请看一下
更新2
,并告诉我您是否认为这是正确的处理方法?非常感谢您的帮助您可能无法在一个响应时间内完成所有记录,因此您可能希望分阶段完成,在请求之间保存游标。根据您使用记录的方式,您可能还希望将现有记录保留在那里——如果您从现在起只使用祖先查询,那就可以了。由于最终的一致性,您对所有记录的查询很可能无法获得所有信息。在删除任何旧记录之前,应确保所有记录都已更新。见本页:
Record.query(ancestor == user.key, Record.record_date == date_parser.parse(json_record['record_date']))