How to remove property on AgensGraph? - agens-graph

I create some vertex on AgensGraph.
And, I want to remove some properties of specific vertex.
agens=# create (:v1{v1:1,v2:2,v3:3});
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 0)
agens=# match (n:v1) return n;
n
------------------------------------
v1[3.1]{"v1": 1, "v2": 2, "v3": 3}
(1 row)
How to remove property on AgensGraph?

You can use REMOVE or SET clause for removing property.
First, use REMOVE clause with property name.
agens=# match (n:v1) remove n.v3 return n;
n
---------------------------
v1[3.1]{"v1": 1, "v2": 2}
(1 row)
Second option, set null to property name.
agens=# match (n:v1) set n.v2 = null return n;
n
------------------
v1[3.1]{"v1": 1}
(1 row)
Thank you.

Related

count jsonb array with condition in postgres

I have a postgres database where some column data are stored as follow:
guest_composition
charging_age
[{"a": 1, "b": 1, "c": 1, "children_ages": [10, 5, 2, 0.1]}]
3
[{"a": 1, "b": 1, "c": 1, "children_ages": [2.5, 1, 4]}]
3
i want to go over the children_ages array and to return the count of children that are above the age of 3. I am having a hard time to use the array data because it is returns as jsonb and not int array.
the first row should return 2 because there are 2 children above the age of 3. The second row should return 1 because there is 1 child above the age of 3.
I have tried the following but it didn't work:
WITH reservation AS (SELECT jsonb_array_elements(reservations.guest_composition)->'children_ages' as children_ages, charging_age FROM reservations
SELECT (CASE WHEN (reservations.charging_age IS NOT NULL AND reservation.children_ages IS NOT NULL) THEN SUM( CASE WHEN (reservation.children_ages)::int[] >=(reservations.charging_age)::int THEN 1 ELSE 0 END) ELSE 0 END) as children_to_charge
You can extract an array of all child ages using a SQL JSON path function:
select jsonb_path_query_array(r.guest_composition, '$[*].children_ages[*] ? (# > 3)')
from reservations r;
The length of that array is then the count you are looking for:
select jsonb_array_length(jsonb_path_query_array(r.guest_composition, '$[*].children_ages[*] ? (# > 3)'))
from reservations r;
It's unclear to me if charging_age is a column and could change in every row. If that is the case, you can pass a parameter to the JSON path function:
select jsonb_path_query_array(
r.guest_composition, '$[*].children_ages[*] ? (# > $age)',
jsonb_build_object('age', charging_age)
)
from reservations r;

Moving PostgreSQL bigint array unique value to another index

How can I move the array bigint value from one index to another? For example, I have an array ARRAY[1, 2, 3, 4] of bigint unique values and want to move value 1 to index 3 so the final result would be ARRAY[2, 3, 1, 4]
The assumptions:
Element in the array identified by the value.
The uniqueness of the elements guaranteed.
Any element can be moved to any place.
Null values not involved on any side.
The value is contained in the array if not we have 2 options. First is do nothing and second handling of this exception by exception mechanism. It's an extreme case that can happen only because of some BUG
Arrays are 1-dimensional.
General assumptions:
Array elements are UNIQUE NOT NULL.
Arrays are 1-dimensional with standard subscripts (1..N). See:
Normalize array subscripts for 1-dimensional array so they start with 1
Simple solution
CREATE FUNCTION f_array_move_element_simple(_arr bigint[], _elem bigint, _pos int)
RETURNS bigint[] LANGUAGE sql IMMUTABLE AS
'SELECT a1[:_pos-1] || _elem || a1[_pos:] FROM array_remove(_arr, _elem) a1'
All fine & dandy, as long as:
The given element is actually contained in the array.
The given position is between 1 and the length of the array.
Proper solution
CREATE FUNCTION f_array_move_element(_arr ANYARRAY, _elem ANYELEMENT, _pos int)
RETURNS ANYARRAY AS
$func$
BEGIN
IF _pos IS NULL OR _pos < 1 THEN
RAISE EXCEPTION 'Target position % not allowed. Must be a positive integer.', _pos;
ELSIF _pos > array_length(_arr, 1) THEN
RAISE EXCEPTION 'Target position % not allowed. Cannot be greater than length of array.', _pos;
END IF;
CASE array_position(_arr, _elem) = _pos -- already in position, return org
WHEN true THEN
RETURN _arr;
WHEN false THEN -- remove element
_arr := array_remove(_arr, _elem);
ELSE -- element not found
RAISE EXCEPTION 'Element % not contained in array %!', _elem, _arr;
END CASE;
RETURN _arr[:_pos-1] || _elem || _arr[_pos:];
END
$func$ LANGUAGE plpgsql IMMUTABLE;
Exceptions are raised if any of the additional assumptions for the simple func are violated.
The "proper" function uses polymorphic types and works for any data type, not just bigint - as long as array and element type match.
db<>fiddle here
Postgresql supports slicing and appending so:
SELECT c, c[2:3] || c[1] || c[4:] AS result
FROM (SELECT ARRAY[1, 2, 3, 4] c) sub
db<>fiddle demo
Another variant using 'WITH .. SELECT ..' avoid searching elements by value, just array element numbers. jsonb[] with big jsons for example.
test_model.data - field to update.
:idx_from, :idx_to - placeholders, 1-based.
WITH from_removed AS (
SELECT
test_model.id,
ARRAY_CAT(
data[: :idx_from - 1],
data[:idx_from + 1 :]
) AS "d"
FROM test_model
)
UPDATE test_model AS source
SET data =
from_removed.d[: :idx_to - 1] ||
data[:idx_from : :idx_from] ||
from_removed.d[:idx_to :]
FROM from_removed
WHERE source.id = from_removed.id AND source.id = :id

How to change VLABEL on AgensGraph?

I want to change vlabel of vertex.
agens=# create (:v1{id:1})-[:e1{id:3}]->(:v1{id:2});
GRAPH WRITE (INSERT VERTEX 2, INSERT EDGE 1)
agens=# match (n:v1{id:1}) set n:v2 remove n:v1;
ERROR: syntax error at or near ":"
LINE 1: match (n:v1{id:1}) set n:v2 remove n:v1;
^
But, there is an error on it.
How to change VLABEL on AgensGraph?
There is no way to change label on vertex on AgensGraph.
But, You can try add new vertex with same properties and remove old vertex.
agens=# create (:v1{id:1})-[:e1{id:3}]->(:v1{id:2});
GRAPH WRITE (INSERT VERTEX 2, INSERT EDGE 1)
agens=# match p = ( (n1)-[r1]->(n2) ) return p;
p
---------------------------------------------------------------
[v1[3.1]{"id": 1},e1[4.1][3.1,3.2]{"id": 3},v1[3.2]{"id": 2}]
(1 row)
agens=# match (n1:v1{id:1})-[r1:e1]->(n2) create (n3:v2)-[r2:e1]->(n2) set n3 = properties(n1), r2 = properties(r1) delete r1, n1;
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 1, DELETE VERTEX 1, DELETE EDGE 1, UPDATE PROPERTY 2)
agens=# match p = ( (n1)-[r1]->(n2) ) return p;
p
---------------------------------------------------------------
[v2[5.1]{"id": 1},e1[4.2][5.1,3.2]{"id": 3},v1[3.2]{"id": 2}]
(1 row)

Determine provided values and copied values in SQL Server instead of update trigger

Let's say I have a table like this:
CREATE TABLE [A]
(
[X] INT,
[Y] INT,
[Z] INT
)
..that has an instead of update trigger. If I insert a row into this table:
INSERT INTO [A]
SELECT 1, 1, 1
Then I hit the update trigger with code like this:
UPDATE [A]
SET [X] = 2
WHERE [X] = 1
I'll end up with an [deleted] table like so:
X: 1,
Y: 1,
Z: 1
I'll end up with an [inserted] table like so:
X: 2,
Y: 1,
Z: 1
Is there any way to determine that only the X was actually set? In other words, how do I distinguish between:
UPDATE [A]
SET
[X] = 2,
[Y] = 1,
[Z] = 1
WHERE [X] = 1
...and the statement above?
Note:
SQL Server 2008
In the trigger, you can add a WHERE clause to compare old and new values and ignore non-changing rows.
There is the function UPDATE() you can use but it can still gives true if the old and new values are the same. It isn't very reliable.
However, there is no way to determine the actual columns in the SET clause of the triggering UPDATE call. That is, these look exactly the same to the trigger
UPDATE [A]
SET
[X] = 2,
[Y] = 1,
[Z] = 1
WHERE [X] = 1
UPDATE [A]
SET [X] = 2
WHERE [X] = 1

In R, how do I extract the column number of a certain row in an array that's closest to a certain value?

Given:
data(veteran)
library(survival)
veteran$prognostic_indicator <- 0
veteran$prognostic_indicator[veteran$karno<50] <- 1
model <- coxph(Surv(time,status)~age+prognostic_indicator,data=veteran)
library(obsSens)
object <- obsSensSCC(model, which = "prognostic_indicator", g0 = seq(1,10,0.01),p0 = c(0.05,0.1,0.2,0.3,0.4), p1 = seq(0, 1, 0.05), logHaz = FALSE, method = "approx")
I can extract the vector:
object$lcl[21,1,1:901]
Which is ordered by descending values. I want to extract the "name" of the number which is closest to 1, but above it. In that case I want to extract the name "2.69" or position 170 since the corresponding number is 1.0001292. The number at position 2.70 is 0.9968844 and thus too low.
How do I extract the position (or name) in a vector of descending values where the number is nearest the value 1.0, but above?
If you create a new vector with that value, then identify the first element that satisfies the condition, then move one back in the sequence.
obj <- object$lcl[21,1,1:901]
obj[which(obj< 1)[1] -1]
# 2.69
#1.000129
The other way would be to work on the reversed vector. Then you do not need to backtrack:
> rev(obj)[which(rev(obj) > 1)[1] ]
2.69
1.000129
Here's another way in addition to DWin's cleaner method.
which.min(subset(object$lcl[21,1,1:901], object$lcl[21,1,1:901] > 1) - 1)

Resources