提问人:zerowords 提问时间:10/8/2012 最后编辑:Communityzerowords 更新时间:10/29/2012 访问量:444
用于删除数据存储中数据的 while 循环
while loop for deleting data in datastore
问:
我试图清理和修改此处答案中的代码以满足我的需要,我只想从模型中删除在 get as 中表示的日期之前的数据记录。Reservations
yy,mm,dd
如果我正确地预测了针对路由的操作,那么我的代码最多只会删除 50 (10*nlimit) 数据记录。cleanTable/2012/10/5
('/cleanTable/([\d]+)/([\d]+)/([\d]+)', CleanTable)
顺便说一句,原始代码的作者(他可能不再订阅 SO)声称他完成此代码的主要技巧是“在 html 中包含重定向而不是使用 self.redirect”。
我不熟悉之类的,但我的直觉是在 for 循环变成 while 循环后添加一个 or 到它。但是我不清楚引发 StopIteration 异常是否真的会导致迭代停止,或者是否需要更多。另外,我不知道如何修改,以便html在提前退出时顺利结束。raise Exception
raise Exception
raise StopIteration
class CleanTable(BaseHandler):
def get(self, yy,mm,dd):
nlimit=5
iyy=int(yy)
imm=int(mm)
idd=int(dd)
param=date(iyy,imm,idd)
q=Reservations.all(keys_only=True)
q.filter("date < ", dt(iyy,imm,idd))
results = q.fetch(nlimit)
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write("""
<html>
<meta HTTP-EQUIV="REFRESH" content="url=http://yourapp.appspot.com/cleanTable">
<body>""")
try:
for i in range(10):
db.delete(results)
results = q.fetch(nlimit, len(results))
for r in results:
logging.info("r.name: %s" % r.name)
self.response.out.write("<p> "+str(nlimit)+" removed</p>")
self.response.out.write("""
</body>
</html>""")
except Exception, inst:
logging.info("inst: %s" % inst)
self.response.out.write(str(inst))
答:
这不是清理模型的最佳方法。更好的方法是获取实体的所有键并创建任务队列。每个队列都会获得一批需要修改的实体的密钥。
另一种方法是创建一个 cron 作业,该作业将查询 x 个最旧的修改实体,修复它们,然后将它们存储回去。
最后,如果你的实体数量如此之多,你也可以考虑使用后端。
希望这会有所帮助。
这是我的更新例程,它已经转换了 500.000 个实体。请务必在后端实例上运行它(您可以将 Queue 定位到后端实例)。请注意,我使用的是光标,这是您可以始终如一地遍历数据的唯一方法(永远不要使用偏移量!
Queue queue = QueueFactory.getQueue("grinderQueue");
queue.add(TaskOptions.Builder.withPayload(new DeferredTask() { //lets generate
private static final long serialVersionUID = 1L;
@Override
public void run() {
String cursor = null;
boolean done = false;
Date now = new Date(1346763868L * 1000L); // 09/04/2012
while(!done) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Venue");
query.setFilter(new FilterPredicate("timeOfLastUpdate", Query.FilterOperator.LESS_THAN,now));
PreparedQuery pq = datastore.prepare(query);
FetchOptions fetchOptions = FetchOptions.Builder.withLimit(1000);
if(cursor != null)
fetchOptions.startCursor(Cursor.fromWebSafeString(cursor));
QueryResultList<Entity> results = pq.asQueryResultList(fetchOptions);
List<Entity> updates = new ArrayList<Entity>();
List<Entity> oldVenueUpdates = new ArrayList<Entity>();
int tuples = 0;
for(Entity en : results) {
tuples++;
try {
if(en.getProperty(Venue.VENUE_KEY) == null)
continue;
Entity newVenue = new Entity("CPVenue",(String)en.getProperty(Venue.VENUE_KEY));
newVenue.setPropertiesFrom(en);
newVenue.removeProperty("timeOfLastVenueScoreCalculation");
newVenue.removeProperty("actionsSinceLastVenueScoreCalculation");
newVenue.removeProperty("venueImageUrl");
newVenue.removeProperty("foursquareId");
newVenue.setProperty("geoCell", GeoCellCalculator.calcCellId(Double.valueOf((String)en.getProperty("lng")), Double.valueOf((String)en.getProperty("lat")),8));
newVenue.setProperty(Venue.TIME_SINCE_LAST_UPDATE, new Date());
updates.add(newVenue);
Venue v = new Venue(newVenue);
//Set timestamp on Venue
en.setProperty("timeOfLastUpdate", now);
oldVenueUpdates.add(en);
}catch(Exception e) {
logger.log(Level.WARNING,"",e);
}
}
done = tuples == 0;
tuples = 0;
if(results.getCursor() != null)
cursor = results.getCursor().toWebSafeString();
else
done = true;
System.out.println("Venue Conversion LOOP updates.. " + updates.size() + " cursor " + cursor);
datastore.put(updates);
datastore.put(oldVenueUpdates);
}
System.out.println("Venue Conversion DONE");
}}));
评论
backend instance
评论