Autoincrement id of an object in array - sql

I need to store array of an objects in postgresql. Structure of object should looks like
{
"id": 1
"title": "XYZ",
"content": "abcabc"
}
My question is how to automatically increment an id ?
Structure of the table looks like
user_id | user_name | notes
The notes column should store the array of objects (notes).
What is the best way to do that, what is the best data type ( json, jsonb,
json[], jsonb[] )?
I'm using flask and postgresql (11).

Use a separate table:
create table user_notes (
user_notes_id serial primary key,
user_id int references users(user_id),
title text,
content text,
created_at timestamp default now()
);
If you want to enumerate the notes for a particular user, use row_number():
select un.*, row_number() over (partition by un.user_id order by un.user_notes_id) as seqnum
from user_notes un
where un.user_id = ?;

Related

How to make human readable autoincrement column in PostgreSQL?

I need to make the column for store serial number of orders in the online shop.
Currently, I have this one
CREATE TABLE public.orders
(
id SERIAL PRIMARY KEY NOT NULL,
title VARCHAR(100) NOT NULL
);
CREATE UNIQUE INDEX orders_id_uindex ON public.orders (id);
But I need to create the special alphanumeric format for storing this number
like this 5CC806CF751A2.
How can I create this format with Postgres capabilities?
You can create a view that simply converts the ID to a hex value:
create view readable_orders
as
select id,
to_hex(id) as readable_id,
title
from orders;

Update value inside json matching a criteria

I have entries (json datatype) in my database with some typos. I want to update them with a correct one
I'm using a PostgreSQL 9.4
This is what I'm trying:
UPDATE table
SET infos = infos || '{ "key1": { "key2": "new text with no typo" } }'
WHERE contact_id = (SELECT contact_id FROM table WHERE infos::TEXT LIKE '%criteria%');
DDL:
CREATE TABLE public.timeline (
contact_id serial NOT NULL,
infos json NULL,
CONSTRAINT contacts_pkey PRIMARY KEY (contact_id)
);
I expect to automatically update all the lines containing the typo.
Solution:
UPDATE table
SET infos = jsonb_set(to_jsonb(infos), '{key1,key2}', '{"key2": "new value to replace"}', false)
WHERE contact_id IN (SELECT contact_id FROM table WHERE infos->'key1'->>'key2' LIKE '%word_to_match%');

PostgreSQL - key-value pair normalization

I'm trying to design a schema (on Postgres but any other SQL's fine) that supports the following requirements:
Each document (a row in table documents) has a unique string ID (id field) and several other data fields.
Each document can have 0 or more tags (which is string key-value pairs) attached to it, and, the goal is to build a system that lets users to sort or filter documents using those string key-value pairs. E.g. "Show me all documents that have a tag of "key1" with "value1" value AND sort the output using the tag value of "key3".
So DDL should look like this: (simplified)
create table documents
(
id char(32) not null
constraint documents_pkey
primary key,
data varchar(2000),
created_at timestamp,
updated_at timestamp
)
create table document_tags
(
id serial not null
constraint document_tags_pkey
primary key,
document_id char(32) not null
constraint document_tags_documents_id_fk
references documents
on update cascade on delete cascade,
tag_key varchar(200) not null,
tag_value varchar(2000) not null
)
Now my question is how can I build a query that does filtering/sorting using the tag key values? E.g. Returns all documents (possibly with LIMIT/OFFSET) that does have "key1" = "value1" tag and "key2" = "value2" tags, sorted by the value of "key3" tag.
You can use group by and having:
select dt.document_id
from document_tags dt
where dt.tag_key = 'key1' and dt.tag_value = 'value1'
group by dt.document_id
order by max(case when dt.tag_key = 'key2' then dt.tag_value end);

Simple tag searching with Sphinx

For example, I have 3 tables:
documents (
id serial PRIMARY KEY,
title character varying(256),
content text,
created timestamp with time zone
);
tags (
id serial PRIMARY KEY,
tag_content character varying(128)
);
tag_assoc (
id serial PRIMARY KEY,
document_id integer,
tag_id integer
);
I would like to be able to search documents for title, content, and for tags.
My sql_query so far is very simple like:
sql_query SELECT id, title, content FROM documents
How would I set up the Sphinx sql_query so that the tags associated with each document are joined to them?
You could use inside sql_query a subselect with group_concat to retrieve them , but a better approach would be to use the sql_joined_field. In your case, would look like:
sql_joined_field = tags from query; tag.assoc.document_id, \
tag_content from tags join tag_assoc on \
tags.id=tar_assoc.tag_id order by tag.assoc.document_id asc

Why does this query only select a single row?

SELECT * FROM tbl_houses
WHERE
(SELECT HousesList
FROM tbl_lists
WHERE tbl_lists.ID = '123') LIKE CONCAT('% ', tbl_houses.ID, '#')
It only selects the row from tbl_houses of the last occuring tbl_houses.ID inside tbl_lists.HousesList
I need it to select all the rows where any ID from tbl_houses exists within tbl_lists.HousesList
It's hard to tell without knowing exactly what your data looks like, but if it only matches the last ID, it's probably because you don't have any % at the end of the string, so as to allow for the list to continue after the match.
Is that a database in zeroth normal form I smell?
If you have attributes containing lists of values, like that HousesList attribute, you should instead be storing those as distinct values in a separate relation.
CREATE TABLE house (
id VARCHAR NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE list (
id VARCHAR NOT NULL,
PRIMARY KEY (id),
);
CREATE TABLE listitem (
list_id VARCHAR NOT NULL,
FOREIGN KEY list_id REFERENCES list (id),
house_id VARCHAR NOT NULL,
FOREIGN KEY house_id REFERENCES house (id),
PRIMARY KEY (list_id, house_id)
);
Then your distinct house listing values each have their own tuple, and can be selected like any other.
SELECT house.*
FROM house
JOIN listitem
ON listitem.house_id = house.id
WHERE
listitem.list_id = '123'