Sequelize Upsert without primary key value in arguments - javascript

So, I have a relation which has the autogenerated id as the primary key and I want it to be that way.
The issue is that whenever I call upsert(), it seems like I have to provide for the primary key value as well in the parameter object which is insane as I wouldn't know what is the id of the particular row I want to edit.
Instead, I am sending mandatorily the value for a unique key that I have defined, but it doesn't work.
Any workarounds or do I need to shift my primary key to some other key of whose value is known?
Example: Let's say I have an Employee table where I have the Employee Id as the PK and their emails as the UNIQUE key. Now, I believe that an upsert operation can still be carried out using a unique key, but that doesn't seem to be possible and I have to tag in the primary key for it.

Related

How to save Item in dynamodb with GSI condition?

I have a dynamodb table that has a Global secondary Index with a range key (email, hashedPassword ).
i want to save an item if the email is not duplicated,
i used attribute_not_exists but it doesn't work, i also used :
ConditionExpression: "#email <> :email",
ExpressionAttributeNames: {"#email": "email"},
ExpressionAttributeValues: {":email": userInfo.email}
without success.
Can anyone help me please,
Thank you.
The condition expression for DynamoDB only works on the item it is working with, and not across items.
In other words, condition expression does not get evaluated against other items.
For example, if you are creating a new item, you can only enforce the email constraint if you use the Primary Key (Partition + Sort Key if you have one) as the unique constraint.
Some options you have:
Perform a read before the insert. This is not going to guarantee uniqueness of the email, but should catch a lot of duplicates.
Use Email as the Primary Key.
Perform a consistent read after the insert, which rolls back the creation
HTH

Issue with mysql command

I have a table called benificiaries with following columns
custid varchar
accno varchar primarykey
name varchar
I have one record in that table with values
101
12345
john
Now I need to insert a record for another custid but same accno
var data={"custid":"102","accno":"12345","name":"john"};
con.query('insert into benificiaries set ?',data)
But it is not allowing since accno is primary key..So how can i insert this?I can have same accountno once for different custid..Any ideas?
Check out your MySQL code here:
CREATE TABLE beneficiaries (
custid INT PRIMARY KEY,
accno INT,
name varchar(30)
);
Set custid as primary keys and observe the datatypes I've used for each column.
That is not possible, you have make accno and custid as composite key
You simply can't do this, because you've defined accno as primary key.
Primary key is exactly that - the primary key of the record. It is a unique value that positively identifies that record and only that record. If you can't guarantee that data to be unique per record, it cannot be your primary key.
This table seems like a mapping table, to me. Is it?
If so, it really doesn't need a primary key. If you absolutely MUST give it a primary key, for some reason, then just give the table a surrogate key using an autoincrementing integer column and make that the primary key for this table.
How is this table being used?
I'd say screw a primary key and just index on both accno and custid columns (if you do lookups by each).
If the combination of accno and custid is unique (probably is, given what this table seems to be), then you can define your primary key as a combination of accno and custid.
If, for some reason, you need to be able to have more than one record with the same values for both of those fields, then you have no natural key in this table anyway.
Because there can be multiple entries with the same accno, accno isn't a primary key. Make a compound primary key from accno and custid, and you should be set.
CREATE TABLE beneficiaries (
custid INT,
accno INT,
name varchar
PRIMARY KEY (custid, accno)
)

JS Knex: getting foreign keys for a table

I want to drop some tables using 'knex' but I have an error Cannot delete or update a parent row: a foreign key constraint fails when I try to drop table with foreign key:
knex.schema.dropTableIfExists(name);
I can use dropForeign() function to drop foreign key but I need to know foreign key name.
How can I get foreign key names using 'knex'?
The usual foreign key index naming format in knex is : tableName_columnName_foreign.
Eg: If you have in table chat a foreign key named visitor_id then its index name will be : chat_visitor_id_foreign
That said,you wouldn't need this, unless someone has explicitly overridden the default foreign key name. In that case , search for it in the migration file or look it up in the database .

How to delete an attribute when sending a partial object update to Algolia?

I need to use partialUpdateObject from the Algolia Javascript SDK to delete an attribute from an object that is already in the index.
My scenario is that I have a description field on my object that is optional. If the user originally sets a description and then later deletes it, I want to remove the description altogether from the object.
I do not want to overwrite the whole object (without the description attribute) because I have some count attributes on the object that I do not want to have to recalculate.
As far as I can tell in the documentation there isn't a way to do it and my workaround is to set the description as an empty string. Is that the recommended approach?
You're right: you cannot totally remove the attribute from an object with a partialUpdateObject operation. As a work-around you can set it to null, maybe that's enough for your use-case?
If you really want to delete the field you can :
Get your object with the search function
Store all fields values
Update (not partial update) your object without passing the field you want to delete

IndexedDB - What is Key, keyPath and indexName?

I am coming from MySQL and I am used to the conventional database table scheme. I am having trouble understanding IndexedDB and some of its terminology. I looked up these definitions in the documentation:
Key
A data value by which stored values are organized and retrieved in the object store.
indexName
The name of the index to create.
keyPath
The key path for the index to use.
Basically, Key is like a Primary Key in MySQL, right? Is indexName the same thing as a column? And I don't understand what a keyPath is.
Can someone explain these for me? Thank you again for you patience :).
Yes, key is like a primary key in SQL. But others seem to be missing an example explaining the main part of your question, and that is the distinction between indexName and keyPath. Per the Mozilla page on creating an index,
indexName
The name of the index to create. Note that it is possible to create an index with an empty name.
keyPath
The key path for the index to use. Note that it is possible to create an index with an empty keyPath, and also to pass in a sequence (array) as a keyPath.
The indexName is what you use to access that index. Indexes are used to search that "column" in the database.
The keyPath is the actual name of the "column." See other questions and answers for what forms a keyPath may take.
Note that "column" is not technically correct, but I'm using it because that's what you used.
For example, suppose your data has the column hours and you want to be able to search your database on that column. When creating your database you would create an index for that column:
objectStore.createIndex(indexName, keyPath, { unique: false });
where indexName can be anything you want, let's say hoursColumn, and keyPath would be hours.
objectStore.createIndex("hoursColumn", "hours", { unique: false });
unique: false just means that other rows of data may have the same value for hours.
I can write data to the objectStore as follows:
db.transaction(storeName, "readwrite").objectStore(storeName).add({hours: 20, minutes: 30});
So to search your data on the column hours, you could write:
var data = db.transaction(storeName).objectStore(storeName).index("hoursColumn").get(20)
and the result would be the first row of data where hours = 20, e.g. {hours: 20, minutes: 30}
So to summarize, indexName is just what you call the index you created that you want to search, and keyPath is the actual name of the stored data on which you want to search.
Indexes are a way to make it possible to query data in the indexeddb database. As you know objects are stored into the objectstores. These objectstore don't have a schema like you have in an normal SQL database.
An index exists out of 3 important properties:
indexName: The indexname is just a name you provide to the index. You will need this name if you want to use the index to query data.
keyPath: This defines which property of the object you want to address in your index. For example: you have an object
{ foo: "bar" }
and you want to query on the foo property, "foo" will be your keypath. The keypath can even go further. You can access nested properties
{ foo: { bar: "bla" } }
If you want to query the bar property the keypath will be "foo.bar"
key: The keys are the values inside the keypath. As you mentioned this key is unique for the index, but this doens't mean this value must be unique over all your objects in the objectstore.
The indexes in the indexeddb work like this:
When you create an index, it creates a new objectstore in which the object will be stored. Instead of storing these object bosed on primary key they are stored based on the values present in the keypath. This means that for a single key in an index you can have multiple objects. So if you start querying an index, it will filter on the keys and return the values that are present in these keys.
Hope this makes indexes clear for you.
I am updating my answer here having re-read the topic of Keys and Indexes. Coming from a MySQL background they are indeed confusing with IndexedDB.
(Please see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Concepts_Behind_IndexedDB#gloss_outofline_key)
Indexes
Typically these occur on elements within your "row" - so for example if you had a row:
{Hello:"World",Foo:"Bar} in your database you could set an index (of any name) on say Hello. This would be like your indexes in MySQL.
Keys
So where Indexes can have multiple, Keys must (as the earlier answer mentions) be unique like MySQL Primary keys. Why this gets confusing is that you can also filter/search your data by Keys as well as Indexes. (see https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange) The difference appears that Key searches appear to be more Ranges (like A-F or > 5 AND < 10) rather than specific values.
There is a very interesting explanation here about keys:
https://golb.hplar.ch/2017/09/A-closer-look-at-IndexedDB.html#primary-keys
Basically it explains that there are 4 types of keys within IndexedDB:
out-of-line : you provide the key yourself on each insert
out-of-line auto generated : primary key (i.e. AutoIncrement) number generated automatically
inline : the contents of field form the index (this is typical to say a MySQL database but must then be unique)
inline auto generated: hidden field (visible in console) added and is accessible through code but not related directly to the object data.
The difference between 2 and 4 is that 2 doesn't get a defined Name, whereas 4 (like a Primary Key in MySQL) does. You could then update (but not insert) on the ID field you've named in 4.
On an aside I believe its called a Keypath because you can call field.subproperty which is quite nice. Please also make sure your keys are spelt correctly! Obvious mistake.
It was also hard for me to understand the difference, but at the end I found out and why most of the time we set them the same name.
In short, the indexName is how we want to the "field" or "column" (index) will be named in our "table" (Object Store) and the keyPath is the property of the stored object that contains the value of the field. Therefore, is logical that they have the same name.
For example, you have a table with following fields:
name
age
They both are the indexName of each field, but you have to tell IndexedDB which property (keyPath) contains the value of each field.
objectStore.createIndex("name", "name", { unique: false });
objectStore.createIndex("age", "age", { unique: false });
Key = Row Item
indexName = Column name
keyPath = Column name

Categories

Resources