Are entity id's idempotent when saving multiple entities with the same id?
I want to ensure only one entity of a specific id exists in my Datastore. I was thinking that I could give it a String id that I create (based off of other data) and if in the future the same entity gets saved again with the same id, the entity will just get overwritten (but two entities will not ever exists).
Am I correct in my thinking or does it not work that way?
An entity key uniquely identifies an Entity. So saving an entity with the same key, but different values is not idempotent, but results in only a single entity. The key for an entity can be thought of as a list of (Kind, name or id) tuples. name would be a string, and id an integer.
In Objectify, if you use #Id with a string, then you'd access that part of the key with getName()
Related
I want to put an order from my lex bot into dynamoDB however the PutItem operation overwrites each time(If the customer name is already in the table).
I know from the documentation that it will do this if the primary key is the same.
My goal is to have each order put into the database so they will be easily searchable in the future.
I have attached some screenshots below. Any help is appreciated
https://imgur.com/a/mLpEkOi
def putDynam(orderNum, table_custName, slotKey, slotVal):
client = boto3.resource('dynamodb')
table = client.Table('blah')
input = {'Customer': table_custName, 'OrderNumber':orderNum[0], 'Bun Type': slotVal[5], 'CheeseDecision': slotVal[1], 'Cheese Type': slotVal[0], 'Pickles': slotVal[4], 'SauceDecision': slotVal[3], 'Sauce Type': slotVal[2]}
action = table.put_item(Item=input)
The primary key is used for identifying each item in the table. There can only be 1 record with a specific primary key (primary keys are unique).
Customer name is not a good primary key, because it's not unique.
In this case you could have an order with some generated Id (orderNumber in your example?), that could be the primary key, and Customer (preferably CustomerId) as a property.
Or you could have a composite primary key made up of CustomerId and OrderId.
If you want to query orders by customer, you could use an index if it's not in the primary key.
I recommend you read up on how DynamoDB works first. You can start with this data modelling tutorial from AWS.
So, basically, the customer name has to be unique, since it's your Primary Key. You can't have two rows with the same primary key. A way could be to have an incremental value that serves as id, and each insert would simply have i+1 as its id.
You can see this stack overflow question for more information: https://stackoverflow.com/a/12460690/11593346
Per https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.put_item, you can:
"perform a conditional put operation (add a new item if one with the specified primary key doesn't exist)"
Note
To prevent a new item from replacing an existing item, use a conditional expression that contains the attribute_not_exists function with the name of the attribute being used as the partition key for the table. Since every record must contain that attribute, the attribute_not_exists function will only succeed if no matching item exists.
Also see DynamoDB: updateItem only if it already exists
If you really need to know whether the item exists or not so you can trigger your exception logic, then run a query first to see if the item already exists and don't even call put_item. You can also explore whether using a combination of ConditionExpression and one of the ReturnValues options (for put_item or update_item) may return enough data for you to know if an item existed.
I only found the way to get children entities by parent one.
But is there any way to retrieve the list of parent entities (by some parent entity's properties filter) with their children in single call?
(Pseudo query):
SELECT * FROM parents (with children) WHERE parent.property1=...
Result should be like this:
- (parent1, child1, child2)
- (parent2, child3, child4)
....
This is not possible if you store the parents and children as separate entities. However, if the children for a parent is expected to be small, then you can consider storing them as embedded struct slice. Then as you query the parent entities and retrieve them you will have access to their children.
The short answer is no.
Some background
Entities in a Datastore mode database form an ancestor path, which means a hierarchically structured space, similar to the directory structure of a file system.
Workarounds:
Depending on your needs there are a couple things that you could do:
You could retrieve each parent and their children individually in multiple calls and then combine all the parts together.
You could use Special query types, such as kindless queries, which is a query with no kind and no ancestor filter that retrieves all of the entities of an application from Datastore, so you can gather the needed information.
Not sure this qualifies as an answer but I have the same scenario and below are the two options I am considering.
The scenario I am in is an Employer kind and an Employee kind. The Employee is a child of Employer but the same Employee can be part of multiple Employers.
I need to find all Employers a specific Employee is part of.
Option 1 (the one I think I will go with)
Have a third entity for a reverse lookup. The key will be the Employee's last part of the key with an additional property to hold the list of Employers' keys.
Every time an Employer/Employee relationship changes I will also update the reverse lookup kind.
Option 2
Have the last part of the Employee's key saved separately in the same entity as an indexed property so that I can search by it (and then able to find each of those entities' parent key).
We inherited a 3rd party database schema where several tables use a database
design pattern in which tables do not define foreign keys directly, but in
a way where some tables do so by a combination of two columns:
a column specifying name of table:
either directly (ENUM type)
or by means of another table (type_id referencing table types, which then contains table name in a varchar column)
a column specifying PK value from said table (e.g. type_value)
This results in a scenario where one row references one table while another
row may reference a completely different table.
We can use query builder and define JOIN and WHERE clauses manually for each
scenario, but it'd be more practical to have one property for each foreign
table and use WHERE clause to filter target table results only, e.g.:
class Foo {
private $id; // PK for Foo
private $type; // string (enum), e.g. 'bar' or 'baz'
private $type_id; // contains PK of Bar or Baz, respectivelly
private $bar; // references entity Bar
private $baz; // references entity Baz
}
The closest thing to what we need which I managed to find is to use Criteria API
to update the WHERE clause dynamically in getter methods (as seen here).
However I'm completely lost in terms of how to setup Doctrine annotations in
this case. Does Doctrine support a DB schema such as this one, or do we have to
fall back to building each query manually via query builder or DQL?
I have a table Object that has 2 fields that are foreign keys (user_id and teacher_id). After generating the Entities for the X table, the entity only contain the $user and $teacher properties, which forces me to use the associated objects instead of id. So supposing I know the user_id and teacher_id for my object, instead of doing:
$object->setUserId(1)
I have to do:
$user = $this->getDoctrine()->getRepository('MyBundle:Users')->find(2);
$object->setUser($user)
is there no way to work directly with the ids to avoid retrieving the entire object associated to each id?
The framework suggests to use objects when setting the association value. Still – are you sure the record isn't loaded in the memory already? If it is, it will not cause additional SQL statement execution.
If you really need to update the association without loading the object, you can
run native SQL;
try creating Doctrine Proxy object manually and setting it instead.
You can get the proxy object using EntityManager method getReference:
$object->setUser($this->getDoctrine()->getReference('MyBundle:Users', 2));
I have an entity that I have deserialized using JMSSerializer. One of the related items is an ArrayCollection that has no entries in it when the parent object is initially created.
The relationship looks like this
Assembly > has many > HistoryEntries
When I try to merge the deserialized Assembly entity where HistoryEntries is an empty ArrayCollection I get the following error
The given entity of type 'XES\\MpmBundle\\Entity\\History' (unassigned) has no identity/no id values set. It cannot be added to the identity map.
How can I merge and persist an entity where one or more of the relationships has no related entities?