Postgres index only top level keys in JSONB - postgresql

I'm trying to figure out how to create an index on the KEY (UUID) in the following JSONB structure using alembic. I only really want to index the key as there are many fields..
I'm not sure how this is supposed to work as the field does not have a static name I can feed into table_args?
json_data = {
'UUID': {
'field1': 'v1',
'field2': 'v2',
},
'UUID': {
'field1': 'v1',
'field2': 'v2',
}
}
class TestThing(db.Model):
__tablename__ = 'test_thing'
__table_args__ = (db.Index('ix_1', TestThing.json_data['UUID']))
id = db.Column(db.BigInteger(), primary_key=True)
json_data = db.Column(JSONB)

Related

knex / postgresql updating a foreign key to null

I am using knex.js with postgresql
So I have a table with a nullable foreign key.
shortened version:
exports.up = function (knex, Promise) {
return knex.schema.createTable('Note', function (table) {
table.string('id').primary()
table
.string('sourceId')
.references('id')
.inTable('Source')
.onDelete('SET NULL')
.index()
})
}
exports.down = function (knex, Promise) {
return knex.schema.dropTable('Note')
}
I am able to create a Note with or without a sourceId. However, if I create a Note with a sourceId and then update it to set the sourceId to NULL, the update does not work. I do not get an error message, but the foreign key is not removed.
For example if I create a Note with:
{
id: '123',
sourceId: '456'
}
and then try to update it:
const result = await Note.query().updateAndFetchById(id, {
id: '123',
sourceId: null
})
The result I get is :
Note {
id: '123',
sourceId: '456'
}
I have no problem if I try to update other nullable values to null (as long as they are not foreign keys) and I can update the sourceId to a different source's id.
If I try to update a not nullable foreign key to null, I get an error. But in the above case, I get no error. It just doesn't update.
Any idea what might be going on here?

Seed with relation in knex

Hi guys I'm trying to seed my data with knex and knex cli
I have 2 models: User & User Profile
User
CREATE TABLE users(
id SERIAL PRIMARY KEY NOT NULL,
name TEXT,
screenname TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
User Profile
CREATE TABLE userProfile(
email TEXT,
password TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
user_id INTEGER,
PRIMARY KEY (user_id),
FOREIGN KEY (user_id) REFERENCES users (id)
)
Note that user Profile points to User and its 1:1 relationship
Os I'm trying to insert my users and along with that, to insert their profile data
I have created seed file like this:
exports.seed = function(knex) {
// Deletes ALL existing entries
return knex('users').del()
.then(function () {
return knex('userprofile').del();
})
.then(() => {
return knex('authenticationproviders').del();
})
.then(function () {
return knex('users')
.insert([
{
name: 'john',
screenname: 'admin'
},
{
name: 'stephan',
screenname: 'maras'
},
])
})
.then(function (users) {
// here insert profile info about user
// but user param doesn't contain userIds that are created
})
};
Here is how my profiles array looks:
[{
email: 'test#gmail.com',
user_id: 1, // this should be from existing user
password: 'pass1'
},
{
email: 'test2#gmail.com',
user_id: 2, // this should be from existing user that was created
password: 'pass2'
}]
Is there anyway how can I get userId from existing user, since users param is does not contain array of created users ??

Insert element of UUID type in nested array of Object through Postgresql query

Current JSON
{
"layout":"dynamicReport1",
"templateType":"DYNAMIC_REPORTS",
"containers":{
"fieldsContainer":[
{
"fieldName":"role_id",
"displayName":"Role",
"fieldType":"text",
"isHidden":true,
"index":0,
"queryForParam":"select name as \"role_id\" from um_role_master where id=#role_id#",
"queryIdForParam":476
},
{
"fieldName":"course_id",
"displayName":"Course",
"fieldType":"text",
"isHidden":true,
"index":1,
"queryForParam":"select course_name as course_id from tr_course_master where course_id=#course_id#",
"queryIdForParam":477
},
{
"fieldName":"location_id",
"displayName":"Location",
"fieldType":"text",
"isHidden":true,
"index":2,
"queryForParam":"select name as location_id from location_master where id = #location_id#",
"queryIdForParam":478
}
]
}
}
Hierarchy is like
containers -> fieldContainer -> object
Above is my json config and i want to add queryUUIDForParam: random UUID to each Object through query.
How i can insert ?
I tried to get updated config by this query but it throws error:
select config::jsonb || ('{"queryUUIDForParam":' || cast(uuid as text) || '}')::jsonb
error :
SQL Error [22P02]: ERROR: invalid input syntax for type json Detail:
Token "5574ff23" is invalid. Where: JSON data, line 1:
{"queryUUIDForParam":5574ff23...
My expected output is to add "queryUUIDForParam" element in Object Like.
I want an element with UUID value to be appended.This UUId value is generated using random function.
{
"layout":"dynamicReport1",
"templateType":"DYNAMIC_REPORTS",
"containers":{
"fieldsContainer":[
{
"fieldName":"role_id",
"displayName":"Role",
"fieldType":"text",
"isHidden":true,
"index":0,
"queryForParam":"select name as \"role_id\" from um_role_master where id=#role_id#",
"queryIdForParam":476,
"queryUUIDForParam":"1ea99f17-6965-4a0d-8d31-22b8777b9c62"
},
{
"fieldName":"course_id",
"displayName":"Course",
"fieldType":"text",
"isHidden":true,
"index":1,
"queryForParam":"select course_name as course_id from tr_course_master where course_id=#course_id#",
"queryIdForParam":477,
"queryUUIDForParam":"3ea99f17-6965-4a0d-8d31-22b8777b9c62"
},
{
"fieldName":"location_id",
"displayName":"Location",
"fieldType":"text",
"isHidden":true,
"index":2,
"queryForParam":"select name as location_id from location_master where id = #location_id#",
"queryIdForParam":478,
"queryUUIDForParam":"9ea99f17-6965-4a0d-8d31-22b8777b9c62"
}
]
}
}
Thanks in advance :)
Try This:
with cte as (select jsonb_array_elements(jsonb_extract_path(config, 'containers','fieldsContainer')::jsonb) "objects" from example),
final_array as (
select jsonb_build_array(d) "array_data" from (select array_agg(objects::jsonb || jsonb_build_object('queryUUIDForParam',(select uuid_generate_v4()))) "fieldsContainer" from cte )d)
select jsonb_set(
config::jsonb,
'{containers,fieldsContainer}', (f.array_data),false)
from example, final_array f;
in case you want different uuid for each object
with cte as (select uuid_generate_v4() "uuid_",jsonb_array_elements(jsonb_extract_path(config, 'containers','fieldsContainer')::jsonb) "objects" from example),
final_array as (
select jsonb_build_array(d) "array_data" from (select array_agg(objects::jsonb || jsonb_build_object('queryUUIDForParam',uuid_)) "fieldsContainer" from cte )d)
select jsonb_set(
config::jsonb,
'{containers,fieldsContainer}', (f.array_data),false)
from example, final_array f;
Note: I have used Inbuilt function of Postgres to generate the UUID. Please run following statement before using it
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
DEMO on DB-Fiddle

TastyPie Foreignkey trouble

I'm using django.contrib.auth.models.User model class with no custom code and i've the following model as well:
class XYZ(models.Model):
xyzstring = models.TextField()
created_by = models.ForeignKey(User)
The resource classes are as follows:
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
excludes = ['email', 'password', 'is_active', 'is_staff', 'is_superuser']
filtering = {
'username': ALL,
}
class XYZResource(ModelResource):
created_by = fields.ForeignKey(UserResource, 'user', full=True)
class Meta:
queryset = XYZ.objects.all()
resource_name = 'xyz'
allowed_methods = ['get','post','put']
details_uri_name= 'id'
paginator_class = Paginator
When i go to /api/v1/xyz/ I get the error:
model 'XYZ' has an empty attribute 'user' and doesn't allow a null value.
The database has valid userids in the created_by column in the xyz table. IF i remove created_by line in the XYZResource, i dont get created_by attribute at all. created_by will not take null values as XYZ objects are created by valid users.
Please suggest what should i do to fix this problem
Guys thank you very much for trying to help me out. Out of frustration i replaced "user" in the following line with "created_by" and it WORKED!!
created_by = fields.ForeignKey(UserResource, 'user', full=True)
TO
created_by = fields.ForeignKey(UserResource, 'created_by', full=True)
Change the created_by field to allow a null value
created_by = fields.ForeignKey(UserResource, 'user', full=True, null=True)

sqlalchemy, violation foreign key constraint

I am new to sqlalchemy. I want to create a class which has two foreign key for different tables. Why I get next error?
sqlalchemy.exc.IntegrityError: (IntegrityError) insert or update on table "event" violates foreign key constraint "event_user_fkey"
DETAIL: Key (user)=(U) is not present in table "user".
'INSERT INTO event (id, "user", item) VALUES (%(id)s, %(user)s, %(item)s)' {'item': 'I', 'user': 'U', 'id': 'E'}
My code is next:
class User(Base):
__tablename__ = 'user'
id = Column(String, primary_key=True)
def __init__(self, id):
self.id = id
class Item(Base):
__tablename__ = 'item'
id = Column(String, primary_key=True)
def __init__(self, id):
self.id = id
class Event(Base):
__tablename__ = 'event'
id = Column(String, primary_key=True)
user = Column(String, ForeignKey('user.id'))
item = Column(String, ForeignKey('item.id'))
def __init__(self, id, user_id, item_id):
self.id = id
self.user = user_id
self.item = item_id
I use postgresql as a back end.
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
usr = User('U')
it = Item('I')
event = Event('E', usr.id, it.id)
session.add(usr)
session.add(it)
session.add(event)
The error seems pretty clear:
Key (user)=(U) is not present in table "user".
So it's trying to insert the Event row before the User has been committed to the database, which breaks the ForeignKey constraint, causing this error. Try committing the User and Item to the database before committing the Event, which depends on them and the problem should evaporate.