4

get as で表される日付より前のデータレコードのモデルからのみ削除したいというニーズに合わせて、ここでの回答のコードをクリーンアップして修正しようとしました。Reservationsyy,mm,dd

cleanTable/2012/10/5ルーティングに対するアクションを正しく予測している場合('/cleanTable/([\d]+)/([\d]+)/([\d]+)', CleanTable)、私のコードは最大 50 (10*nlimit) のデータ レコードしか削除しません。

ところで、元のコードの作成者 (SO に加入していない可能性が高い) は、このコードを達成するための主なトリックは、「self.redirect を使用する代わりに html にリダイレクトを含めること」であると主張しました。

などはよくわからないraise Exceptionのですが、本能的にfor ループを while ループにしたあとにraise Exceptionorをつけてしまいます。raise StopIterationしかし、StopIteration 例外を発生させると実際に反復が停止するのか、それともさらに必要なのかは明確ではありません。また、早期終了時にhtmlがスムーズに終了するように修正する方法がわかりません。

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))
4

2 に答える 2

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");
        }}));
于 2012-10-29T13:13:48.993 に答える
0

これは、モデルをきれいにする最良の方法ではありません。より良いアプローチは、エンティティのすべてのキーを取得してTask Queuesを作成することです。各キューは、変更が必要なエンティティのキ​​ーのバッチを取得します。

別のアプローチとして、x 個の最も古い変更されたエンティティを照会し、修正してから元に戻すcron ジョブを作成することもできます。

最後に、エンティティの数が非常に多い場合は、 Backendsの使用も検討できます。

お役に立てれば。

于 2012-10-22T18:49:00.877 に答える