2010-11-18 8 views
4

ich alle Daten in einem Namensraum kopieren kopieren möchten, sagen www.mysite.com, zu einem anderen Namespace, sagen nightly.latest.mysite.appspot.com. Was ist der beste Weg, dies zu tun?Wie Datenspeicherentitäten zwischen Namespaces

Die Beispiele Namespaces sind nicht zufällig: sie sind die Namespaces, die von einem NamespaceFilter für die gegebenen Domänen festgelegt sind, die die App dienen.

Ich möchte alle ziehen können, die ‚Herstellung‘ von Daten in einen ‚nicht-Produktion‘ Namensraum für die Prüfung.

+1

Glauben Sie, dass der RAS-API Sie bei diesem Unterfangen helfen kann? Sie müssen das Python-SDK herunterladen, aber Sie können es für Ihre Java-Anwendung einrichten. Ich habe gerade dieses Kapitel in "Programmieren von Google App Engine" gestern über Bulk-Datenoperationen und Fernzugriff gelesen: http://my.safaribooksonline.com/web-development/9780596157517/bulk-data-operations-and-remote- access/using_the_remote_api_from_a_script # X2ludGVybmFsX0ZsYXNoUmVhZGVyP3htbGlkPTk3ODA1OTYxNTc1MTcvMjc3 –

+0

Ja, meine Annahme ist die remote_api und ihre Massendatenoperationen müssen verwendet werden, ich weiß einfach nicht wie und will das Rad nicht neu erfinden. –

+0

Wenn Sie den Bulk Loader-Ansatz verwenden möchten, müssen Sie auch eine Python-Instanz Ihrer App hochladen. Docs sind hier: http://code.google.com/appengine/docs/python/tools/uploadingdata.html –

Antwort

1

Leider gibt es derzeit keine automatische Möglichkeit, dies zu tun.

Sie werden in einer Schleife über alle Daten haben und es zu dem neuen Namensraum wieder speichern. Sie können über Java und Namespaces in der multitenancy Dokumentation lesen.

+0

Ich bin mir sicher, dass ich Probleme mit der Zeitüberschreitung bei diesem Ansatz haben werde, also ist das nicht trivial, was mich zögerlich macht, diesen Weg zu gehen. –

+0

Sie müssen Abfragecursor und die Aufgabenwarteschlange dafür verwenden, wie viele andere Aufgaben in App Engine. –

+0

ja. Das fühlt sich an wie ein eigenständiges Projekt. –

6

Namespace ist der Teil des Schlüssels. Sie können also nicht alle Daten von einem Namespace in einen anderen ändern oder kopieren. Nach meinem Verständnis können Sie nur alle Objekte aus einem Namespace abrufen und NEUE Objekte mit denselben Eigenschaften in einem anderen Namespace erstellen.

+0

guten Fang, das hatte ich vergessen. –

4

Ich verwende appengine-mapreduce dafür. Ich werde nicht darauf eingehen, es im Detail aufzustellen. Sie können die getting started guides für diese Information lesen.

Gerade jetzt müssen Sie jeden Klassennamen eingeben kopiert werden. TODO stellt fest, wie man alle __Stat_Kind__ Ergebnisse programmatisch überschleifen kann, so dass jede Art/Klasse nicht separat spezifiziert werden muss.

import java.util.logging.Logger; 

import org.apache.hadoop.io.NullWritable; 

import com.google.appengine.api.NamespaceManager; 
import com.google.appengine.api.datastore.DatastoreService; 
import com.google.appengine.api.datastore.DatastoreServiceFactory; 
import com.google.appengine.api.datastore.Entity; 
import com.google.appengine.api.datastore.Key; 
import com.google.appengine.api.datastore.KeyFactory; 
import com.google.appengine.tools.mapreduce.AppEngineMapper; 

public class DatastoreCopyMapper extends 
     AppEngineMapper<Key, Entity, NullWritable, NullWritable> { 

    private static final Logger log = Logger 
      .getLogger(DatastoreCopyMapper.class.getName()); 
    private static String destination; 

    public DatastoreCopyMapper() { 
    } 

    @Override 
    public void taskSetup(Context context) { 
     log.warning("Doing per-task setup"); 
     destination = context.getConfiguration().get("destination"); 
     log.warning("destination: " + destination); 
    } 

    @Override 
    public void map(Key key, Entity value, Context context) { 

     NamespaceManager.set(destination); 
     String name = key.getName(); 
     long id = key.getId(); 
     Key destinationKey = null; 
     if (name != null) { 
      destinationKey = KeyFactory.createKey(key.getKind(), name); 
     } else if (id != 0) { 
      destinationKey = KeyFactory.createKey(key.getKind(), id); 
     } 
     Entity destinationEntity = new Entity(destinationKey); 
     destinationEntity.setPropertiesFrom(value); 
     DatastoreService datastore = DatastoreServiceFactory 
       .getDatastoreService(); 

     datastore.put(destinationEntity); 

    } 
} 

mapreduce.xml

<configurations> 
    <configuration name="Copy between namespaces"> 
    <property> 
     <name>mapreduce.map.class</name> 
     <value>com.mysite.server.DatastoreCopyMapper</value> 
    </property> 
    <property> 
     <name>mapreduce.inputformat.class</name> 
     <value>com.google.appengine.tools.mapreduce.DatastoreInputFormat</value> 
    </property> 
    <property> 
     <name human="Entity Kind to Map Over">mapreduce.mapper.inputformat.datastoreinputformat.entitykind</name> 
     <value template="optional">User</value> 
    </property> 

    <property> 
     <name human="Destination Namespace">mapreduce.mapper.inputformat.datastoreinputformat.destination</name> 
     <value template="optional">dev.mysite.com</value> 
    </property> 

    </configuration> 
</configurations>