I would like to keep a list of 'things' in Datastore. No other information other than their names are required for these 'things', and these names must be unique, i.e. they can be thought as key_name for an entity. In this case, I don't need any explicit property/field for the entity kind (since the name of a 'thing' can be kept inside key_name of an entity). Is this possible? How? The alternative is to replicate this piece of information by having a dedicated field/property for name.
class EntityKindWithNoProperty(db.Model):
name = db.StringProperty()
I feel like this approach is duplication of information. What do you think?
This works
class Empty(ndb.Model):
pass
e = Empty(id="somestring")
e.put()
For uniqueness you can potentially generate the IDs in advance then consume them one by one with numeric keys. Or, depending on your use model, get_or_insert.
Have you considered having a single entity with a list property?
class ThingSingleton(db.Model):
things = db.StringListProperty()
The best approach to use would depend on your query patterns and the expected cardinality of things.
Related
Using MongoAlchemy, is it possible to have a DocumentField that can be one of two types? E.g:
class A(Document):
foo = StringField()
class B(Document):
bar = StringField()
class C(Document):
child = DocumentField(A or B)
I thought of a few options that might work:
Give A and B a common parent and then do child = DocumentField(CommonParent).
Write a custom Field that overrides DocumentField, but changes the validator to search through a list of types, instead of one.
Just use an AnythingField. Kinda defeats the point.
But wondered if it was already done?
There was a branch that I never merged (although I did use it for a while) where I implemented polymorphic types:
https://github.com/jeffjenkins/MongoAlchemy/tree/poly-queries
If you're willing to do a bit of bug fixing that's a pretty good option.
Otherwise the easiest thing to do is implement a custom field. I suspect it might be easier to create a regular field that took a list of DocumentFields as inputs and which could distinguish than to mess with DocumentField (which is sort of what the polymorphism branch does, but more complexly).
My entities can currently be viewed using the path /12345 where 12345 represents its entity ID.
I want to create a handler which deletes any entity using /12345/delete.
The handler would look something like this:
class DeleteHandler(BaseHandler):
def get(self, entity_id):
# cannot retrieve entity using just entity_id
# We cannot use KIND.get_by_id(entity_id), since 'entity kind' is unknown
How can we get the entity kind using the url, so that we may use get_by_id() to retrieve the entity, and then delete it?
Am I approaching this correctly? Or is there a better way?
Entity ids are not unique across kinds, so I don't really know how you are expecting this to work.
The websafe encoded version of the full key, however, does give enough information to uniquely identify the entity. You can then use that to instantiate a key, and you can call delete on that key.
It doesn't feel right.
I would go simply with kind/12345/delete
To answer your question, one approach could be with whitelisting.
Set somewhere the kinds (classes) you want this operation to delete their objects (entities).
Suppose you have these Kinds:
class Foo(ndb.Expando):
pass
class Boo(ndb.Expando):
pass
class Bar(ndb.Expando):
pass
Now since you have the id:
kinds_to_delete = ['Foo', 'Boo', 'Bar']
for kind_to_delete in kinds_to_delete:
ndb.Key(kind_to_delete, entity_id).delete()
Or as a dirty oneliner:
[ndb.Key(kind, entity_id).delete() for kind in ['Foo', 'Boo', 'Bar']]
/<key>/delete
Maybe it's easier if you passed around the base64 representation of the key
Sorry for noobster question again.
But I'm trying to do some very easy stuff here, and I don't know how. Documentation gives me hints which do not work, or apply.
I recieve a POST request and grab a variable out of it. It says "name".
I have to search all over my entities Object (for example) and find out if there's one that has the same name. Is there's none, I must create a new Entity with this name. Easy it may look, but I keep Failing.
Would really appreciate any help.
My code currently is this one:
objects_qry = Object.query(Object.name == data["name"])
if (not objects_qry ):
obj = Object()
obj .name = data["name"]
obj .put()
class Object(ndb.Model):
name = ndb.StringProperty()
Using a query to perform this operation is really inefficient.
In addition your code is possibly unreliable, if name doesn't exist and you have two requests at the same time for name you could end up with two records. And you can't tell because your query only returns the first entity with the name property equal to some value.
Because you expect only one entity for name a query is expensive and inefficient.
So you have two choices you can use get_or_insert or just do a get, and if you have now value create a new entity.
Any way here is a couple of code samples using the name as part of the key.
name = data['name']
entity = Object.get_or_insert(name)
or
entity = Object.get_by_id(name)
if not entity:
entity = Object(id=name)
entity.put()
Calling .query just creates a query object, it doesn't execute it, so trying to evaluate is as a boolean is wrong. Query object have methods, fetch and get that, respectively, return a list of matching entities, or just one entity.
So your code could be re-written:
objects_qry = Object.query(Object.name == data["name"])
existing_object = objects_qry.get()
if not existing_object:
obj = Object()
obj.name = data["name"]
obj.put()
That said, Tim's point in the comments about using the ID instead of a property makes sense if you really care about names being unique - the code above wouldn't stop two simultaneous requests from creating entities with the same name.
i will like to have two types of entities referring to each other.
but python dont know about name of second entity class in the body of first yet.
so how shall i code.
class Business(db.Model):
bus_contact_info_ = db.ReferenceProperty(reference_class=Business_Info)
class Business_Info (db.Model):
my_business_ = db.ReferenceProperty(reference_class=Business)
if you advice to use reference in only one and use the implicitly created property
(which is a query object) in other.
then i question the CPU quota penalty of using query vs directly using get() on key
Pleas advise how to write this code in python
Queries are a little slower, and so they do use a bit more resources. ReferenceProperty does not require reference_class. So you could always define Business like:
class Business(db.Model):
bus_contact_info_ = db.ReferenceProperty()
There may also be better options for your datastructure too. Check out the modelling relationships article for some ideas.
Is this a one-to-one mapping? If this is a one-to-one mapping, you may be better off denormalizing your data.
Does it ever change? If not (and it is one-to-one), perhaps you could use entity groups and structure your data so that you could just directly use the keys / key names. You might be able to do this by making BusinessInfo a child of Business, then always use 'i' as the key_name. For example:
business = Business().put()
business_info = BusinessInfo(key_name='i', parent=business).put()
# Get business_info from business:
business_info = db.get(db.Key.from_path('BusinessInfo', 'i', parent=business))
# Get business from business_info:
business = db.get(business_info.parent())
I'm trying to build an elixir model in which I have a class with a list(of variable size) of tuples.
One example would be a recipe
while I can do something like this:
class Recipe(Entity):
ingrediants = OneToMany('IngrediantList')
cooking_time = Field(Integer)
...
class IngrediantList(Entity):
ingrediant = ManyToOne('Ingrediant')
quantity = Field(Number(3,2))
class Ingrediant(Entity):
name = Field(String(30))
...
It has a number of short comings. For one, I don't like creating an entity for ingrediant list which I don't have any meaning for wrt the domain; takes fun out of abstraction.
Another is that a query like which items can I prepare with this ingredient would get really messy and probably inefficient without adding more relations and or fields to the model making it messy in turn.
One more example would be a bank deposit slip with list of denominations and quantity.
What is the best way to design such a model?
This is the correct way to model composite objects. The only thing I'd change is the name of the IngredientList class. Something like RecipeEntry or IngredientQuantity would be more appropriate. Calling it a tuple is just trying to avoid the need to name the fact that a recipe needs some quantity of some ingredient.
If for most of the code you don't want to consider the details of the association you can use sqlalchemy associationproxy extension to create a proxy attribute to hide the details.
solution using sqlalchemy associationproxy
This is from the sqlalchemy docs.