while循环用于删除数据存储区中的数据

时间:2012-10-07 16:22:35

标签: python google-app-engine exception while-loop

我尝试在答案here中根据我的需要清理和修改代码,我只想从模型Reservations中删除get as {中表达的日期之前的数据记录{1}}。

如果我正确地预测yy,mm,dd对路由cleanTable/2012/10/5的操作,那么我的代码最多只能删除50(10 * nlimit)个数据记录。

Btw,原始代码的作者(可能不再订阅SO)声称他完成此代码的主要技巧是“在html中包含重定向而不是使用self.redirect”。

我不熟悉('/cleanTable/([\d]+)/([\d]+)/([\d]+)', CleanTable)之类的内容,但我的本能是在for循环中将for raise Exceptionraise Exception添加到for循环中。但是我不清楚是否提高StopIteration异常会导致迭代停止或是否需要更多。此外,我不知道如何修改,以便html在提前退出时顺利结束。

raise StopIteration

2 个答案:

答案 0 :(得分:0)

这不是清洁模型的最佳方法。更好的方法是获取实体的所有密钥并创建Task Queues。每个队列将获得需要修改的实体的一批密钥。

另一种方法也是创建一个cron job,它将查询x个最旧的修改实体,修复它们然后再存储它们。

最后,如果您的实体数量如此巨大,您还可以考虑使用Backends

希望这有帮助。

答案 1 :(得分:0)

这是我的更新例程,它已经转换了500.000个实体。确保在后端实例上运行它(您可以将队列定位到后端实例)。请注意,我正在使用游标,这是您可以始终迭代数据的唯一方法(从不使用偏移!)。

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");
        }}));