I have an array of jsonb elements (jsonb[]), with id and text. To remove an element I could use:
UPDATE "Users" SET chats = array_remove(chats, '{"id": 2, "text": "my message"')
But I want to delete the message just by the id, cause getting the message will cost me another query.
Assuming missing information:
Your table has a PK called user_id.
You want to remove all elements with id = 2 across the whole table.
You don't want to touch other rows.
id is unique within each array of chats.
UPDATE "Users" u
SET chats = array_remove(u.chats, d.chat)
FROM (
SELECT user_id, chat
FROM "Users", unnest(chats) chat
WHERE chat->>'id' = '2'
) d
WHERE d.user_id = u.user_id;
The following explanation matches the extent of provided information in the question:
Related
Let's say I have a table students with a column type jsonb where I store a list with students' additional emails. A student row looks like this
student_id
name
emails
1
John Doe
[j.doe#email.com]
I'm using the following query to update the emails column:
UPDATE students SET emails = emails || '["j.doe#email.com"]'::jsonb
WHERE student_id=1
AND NOT emails #> '["j.doe#email.com"]'::jsonb;
Once the column emails is filled, if I reuse query above with the parameter ["j.doe#email.com", "john#email.com"], the column emails would be update with repeated value:
student_id
name
emails
1
Student 1
[j.doe#email.com, j.doe#email.com, john#email.com]
Is there a way to make sure that in the column emails I'll always have a jsonb list with only unique values ?
Use this handy function which removes duplicates from a jsonb array:
create or replace function jsonb_unique_array(jsonb)
returns jsonb language sql immutable as $$
select jsonb_agg(distinct value)
from jsonb_array_elements($1)
$$;
Your update statement may look like this:
update students
set emails = jsonb_unique_array(emails || '["j.doe#email.com", "john#email.com"]'::jsonb)
where student_id=1
and not emails #> '["j.doe#email.com", "john#email.com"]'::jsonb
Test it in db<>fiddle.
i have two records ('orders' and 'menulist') that are joined with 'orderitem' by orderID nad menuID
[1]: https://i.stack.imgur.com/5kF8R.png
[2]: https://i.stack.imgur.com/sabUE.png
[3]: https://i.stack.imgur.com/0sqk1.png
i was trying to promote each orderitem record into a relationship in the graph
what I did is:
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
CREATE (n:Orders)
SET n = row
LOAD CSV WITH HEADERS FROM "file:///menulist.csv" AS row
CREATE (n:Menu)
SET n = row
CREATE INDEX FOR (m:Menu) ON (m.MenuID)
CREATE INDEX FOR (o:Orders) ON (o.OrderID)
LOAD CSV WITH HEADERS FROM "file:///orderitem.csv" AS row
MATCH (m:Menu), (o:Orders)
WHERE m.MenuID = row.MenuID AND o.orderID = row.orderID
CREATE (o)-[oi:CONTAINS]->(m)
SET oi = row,
oi.Quantity = toInteger(row.Quantity)
but I got (no changes, no records), seems there is an error here, can anyone help to solve?
That is not the proper way of creating node from csv. Follow the examples found in this link: https://neo4j.com/docs/cypher-manual/current/clauses/load-csv/#load-csv-import-data-from-a-csv-file
In your example, remove the Set n = row because it will not assign the columns in the csv to each property in the node. You need to define the attributes one at a time. See below.
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
CREATE ( :Orders {ID: row.OrderID, <and so on> , paymentID: row.PaymentID })
Also notice that the variable n in label :Orders is not needed.
I was curious if it's possible to SELECT a specific index from a list collection in Cassandra. Say I have:
CREATE TABLE users (
user_id text PRIMARY KEY,
order_list list<text>
);
UPDATE users
SET ordered_list = [ 'thing1', 'thing2', 'thing3' ] WHERE user_id = 'user1';
Is it possible to then get back an index of ordered_list, such as ordered_list[1] from a CQL query instead of the entire list?
No, you can't. You can UPDATE and DELETE with subscripts, but not SELECT or INSERT.
I am trying to limit the about of tables in my database because I hear that's good (I am a novice web developer). I want to have the user input a list into the database. So they input a title, overall comment, and then start making the list. I can't figure out how to do this without making a new table for each list. Because, say one user wants a list with 44 values and another user wants a list of 10 values. I can't think of how to do this without making a new table for each list. I would really appreciate any help/insight you can give to me.
Basically, you want to make a table for the user lists, where each row in the table refers to one user's lists, and another table for the user list values, where each row in the table has a column for a reference to the list it belongs to, and a column for the value the user input.
Your Table Could Be:
UserID, int
ListID, int (Primary Key-Unique Identifier)
Title, VarChar(250)
Comment, VarChar(MAX)
Example Content:
1 | 1 | The Title | My Comment
1 | 2 | The Other Title | My other comment
2 | 3 | First Comment | Second Person, first comment
Eacher User just gets their list from a query:
Select ListID, Titel, Comment FROM the_Table
where UserID = #UserID
You can get away with a single table of lines for all the lists, say for example simply
CREATE TABLE ListLines (
listID INTEGER,
lineNo INTEGER,
line TEXT,
PRIMARY KEY (listID, lineNo),
FOREIGN KEY (listID) REFERENCES Lists
);
with the table of lists becoming:
CREATE TABLE Lists (
listID INTEGER PRIMARY KEY,
userID INTEGER,
title TEXT,
comment TEXT,
FOREIGN KEY (userID) REFERENCES Users
);
assuming you have a Users table with primary key userID INTEGER with per-user information (name, etc, etc).
So to get all the lines of a list given its ID you just
SELECT line FROM ListLines
WHERE listID=:whateverid
ORDER BY lineNo;
or you could UNION that with e.g. the title:
SELECT title AS line FROM Lists
WHERE listID=:whateverid
UNION ALL
SELECT line FROM ListLines
WHERE listID=:whateverid
ORDER BY lineNo;
and so on. This flexible and efficient arrangement is the relational way of doing things...
Web app is being written in classic ASP with a MSSQL backend. On this particular page, the admin can select 1 or any/all of the employees to assign the project to. I'm trying to figure out a simple way to store the employee IDs of the people assigned to it in one column.
The list of employees is generated from another table and can be dynamic (firing or hiring) so I want the program to be flexible enough to change based on these table changes.
Basically need to know how to assign multiple people to a project that can later be called up on a differen page or from a different query.
Sorry for the n00bish question, but thanks!
Don't store multiple ID's in one column! Create another table with the primary key of your existing table and a single ID that you want to store. You can then insert multiple rows into this new table, creating a 1:m (one to many) relationship. For example, let's look at an order table:
order:
order_id
order_date
and I have a product table...
product:
product_id
product_name
Now, you could go down the road of adding a column to order that let you list the products in the order, but that would be bad form. What you want instead is something like..
order_item:
order_item_id
order_id
product_id
quantity
unit_price
You can then perform a join to get all of the products for a particular order...
select
product.*
from orders
inner join order_item on order_item.order_id = order.order_id
inner join product on product.product_id = order_item.product_id
where orders.order_id = 5
Here's an example order_id of 5, and this will get all of the products in that order.
You need to create another table that stores these values such as. So this new table would store one row for each ID, and then link back to the original record with the original records ID.