user291701
user291701

Reputation: 39731

Add a new attribute to entity in datastore?

I have an entity in my app engine datastore. There's actually only one instance of this entity. I can see it in my admin console. Is it possible to add a new attribute to the entity via the admin console (using gql perhaps)?

Right now it looks something like:

Entity: Foo
Attributes:  mName,  mAge,  mScore

and I'd like to add a new boolean attribute to this entity like "mGraduated" or something like that.

In the worst case I can write some code to delete the entity then save a new one, but yeah was just wondering.

Thanks

-------- Update ---------

Tried adding the new attribute to my class (using java) and upon loading from the datastore I get the following:

java.lang.NullPointerException: 
  Datastore entity with kind Foo and key Foo(\"Foo\") has a null property named mGraduated.  
  This property is mapped to com.me.types.Foo.mGraduated, which cannot accept null values.

This is what my entity class looks like, I just added the new attribute (mGraduated), then deployed, then tried loading the single entity from the datastore (which produced the above exception):

@PersistenceCapable
public class Foo
{   
  @PrimaryKey
  private String k;

  /** Some old attributes, look like the following. */
  @Persistent
  @Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
  private String mName;

  ... 

  /** Tried adding the new one. */
  @Persistent
  @Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
  private boolean mGraduated;

Upvotes: 4

Views: 5351

Answers (3)

Marek Halmo
Marek Halmo

Reputation: 2199

The only way to implement this is to use Boolean as the type for the new property..

Than in set method you can accept boolean value, that's no issue.

If you want the get method to also return boolean.. you also can, but be sure to check if the value is null and if so.. return default value (e.g. true)

so

private Boolean newProp = null; // can also assing default value .. e.g. true;

public void setNewProp(boolean val)
{
    this.newProp = val;
}

public boolean getNewProp()
{
    if(this.newProp == null)
        return true; // Default value if not set

    return this.newProp.booleanValue();

}

I recommend you not to migrate your data in this case - it can be very costly and can deplete your quota easily (read old data, create new, delete old = 3 operations for every entry in you data store)

Upvotes: 2

Dan Sanderson
Dan Sanderson

Reputation: 2111

You have declared the new mGraduated field using the primitive type boolean, which cannot be null. The existing entity can't be loaded into the model class because it doesn't have this property. One option is to declare this property using the Boolean class, which can accept a null value.

The Admin Console only knows about properties in existing entities. You cannot use the Admin Console directly to create a new property with a name not used by any existing entities. (This is just a limitation of the Console. App code can do this easily.)

Upvotes: 0

Amy U.
Amy U.

Reputation: 2237

You can't do this through the admin console, but you shouldn't have to delete the entity. Instead just update it- the Datastore does not enforce schemas for Kinds. E.g., if Foo is a subclass of db.Model (Python), change your model subclass to include the new property; fetch the model instance (e.g., by its key), update the instance, including setting the value of the new field; and save the modified instance. Since you just have one instance this is easy. With many such instances to update you'd probably want to do this via task queue tasks or via a mapreduce job.

Upvotes: 1

Related Questions