Can we get graphID(Oid) of a graph on postgresql terminal - postgresql

I have created a graph called 'cyc_graph', Now I'm testing to see if I can insert some vertices in this graph using the agtype_build_map function, but this function requires graphID as a parameter. So How can I get the graphID of a graph already created from PostgreSQL terminal?
I tried something like this
SELECT 'cyc_graph.vtxs'::regclass::oid;
But this gives Oid of vtxs table. (vtxs is label name for vertices). I understand that cyc_graph is a schema name. So I don't know how can I get graphID/Oid of a schema name.

Inside the terminal, after loading AGE extension and setting search_path, use the command:
SELECT oid, name
FROM ag_graph;
It will output something like this:
oid | name
--------+-------------------
72884 | graph1
353258 | graph2
353348 | graph3
(3 rows)
The column oid is the Oid of the graphs.
But maybe you want to do it from the source code?
Call the function search_graph_name_cache(char* graph_name);
(located here)
It will return a pointer to a struct defined as graph_cache_data, which has the Oid of the graph.

What is GraphID?
Simple entities are assigned a unique graphid. A graphid is a unique composition of the entity’s label id and a unique sequence assigned to each label. Note that there will be overlap in ids when comparing entities from different graphs.
Reference: https://age.apache.org/age-manual/master/intro/types.html
test=# LOAD 'age';
LOAD
test=# SET search_path = ag_catalog, "$user", public;
SET
test=# SELECT * FROM cypher('graph', $$
MATCH (v)
RETURN v
$$) as (v agtype);
v
------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Person", "properties": {"name": "John"}}::vertex
{"id": 844424930131970, "label": "Person", "properties": {"name": "Jeff"}}::vertex
{"id": 844424930131971, "label": "Person", "properties": {"name": "Joan"}}::vertex
{"id": 844424930131972, "label": "Person", "properties": {"name": "Bill"}}::vertex
{"id": 844424930131973, "label": "Person", "properties": {"name": "Andres", "title": "Developer"}}::vertex
(5 rows)
Here the id is actually GraphID.

Related

Apache AGE - Creating Materialized View Error

I wanted to create a materialized view from a label table and then create indexes on it. However, when I type the query to create this view, postgres pops an error.
Here is the query that I type to return all the vertices containing the "Book" label :
demo=# SELECT * FROM cypher ('demo', $$
demo$# MATCH (v:Book)
demo$# RETURN v
demo$# $$) as (vertex agtype);
vertex
---------------------------------------------------------------------------------------------------------------------------------------
{"id": 1125899906842625, "label": "Book", "properties": {"title": "The Hobbit"}}::vertex
{"id": 1125899906842626, "label": "Book", "properties": {"title": "SPQR: A History of Ancient Rome", "author": "Mary Beard"}}::vertex
(2 rows)
Here is the way that I'm creating the materialized view :
demo=# CREATE MATERIALIZED VIEW book_view AS SELECT * FROM cypher ('demo', $$
MATCH (v:Book)
RETURN v.author, v.title
$$) as (author agtype, title agtype);
ERROR: unhandled cypher(cstring) function call
DETAIL: demo

PostgreSQL update a jsonb column multiple times

Consider the following:
create table query(id integer, query_definition jsonb);
create table query_item(path text[], id integer);
insert into query (id, query_definition)
values
(100, '{"columns":[{"type":"integer","field":"id"},{"type":"str","field":"firstname"},{"type":"str","field":"lastname"}]}'::jsonb),
(101, '{"columns":[{"type":"integer","field":"id"},{"type":"str","field":"firstname"}]}'::jsonb);
insert into query_item(path, id) values
('{columns,0,type}'::text[], 100),
('{columns,1,type}'::text[], 100),
('{columns,2,type}'::text[], 100),
('{columns,0,type}'::text[], 101),
('{columns,1,type}'::text[], 101);
I have a query table which has a jsonb column named query_definition.
The jsonb value looks like the following:
{
"columns": [
{
"type": "integer",
"field": "id"
},
{
"type": "str",
"field": "firstname"
},
{
"type": "str",
"field": "lastname"
}
]
}
In order to replace all "type": "..." with "type": "string", I've built the query_item table which contains the following data:
path |id |
----------------+---+
{columns,0,type}|100|
{columns,1,type}|100|
{columns,2,type}|100|
{columns,0,type}|101|
{columns,1,type}|101|
path matches each path from the json root to the "type" entry, id is the corresponding query's id.
I made up the following sql statement to do what I want:
update query q
set query_definition = jsonb_set(q.query_definition, query_item.path, ('"string"')::jsonb, false)
from query_item
where q.id = query_item.id
But it partially works, as it takes the 1st matching id and skips the others (the 1st and 4th line of query_item table).
I know I could build a for statement, but it requires a plpgsql context and I'd rather avoid its use.
Is there a way to do it with a single update statement?
I've read in this topic it's possible to make it with strings, but I didn't find out how to adapt this mechanism with jsonb treatment.

How to use IN for search in JSON-b with index?

I have table with JSON-b field like this:
id | data
----------
1 | '{"points": [{"id": 10, "address": "Test 1"}, {"id": 20, "address": "Test 2"}, {"id": 30, "address": "Test 3"}]}'
2 | '{"points": [{"id": 40, "address": "Test 444"}, {"id": 20, "address": "Test 222"}, {"id": 50, "address": "Test 555"}]}'
The JSON-b field "data" contains "points" array.
How to get all "points" whose point id is contained in an array [40, 20]? Like classic IN:
... IN (40,20)
Query must use GIN index!!! Array IDs will be sub-query.
You could almost do it with a functional index using a jsonb_path_query_array to extract the data. But as far as I can tell, not quite.
create index on t using gin (jsonb_path_query_array(x,'$.points[*].id'));
And then query with:
select * from t where jsonb_path_query_array(x,'$.points[*].id') ?| '{20,40}';
The problem is that ?| only works with text elements, while in your data the values of 'id' are integers, not text. I thought jsonpath would provide a way to convert them to text, but if it does, I cannot find it.
So instead I think you will have to define your own function which accepts jsonb, and returns int[] or text[] (or jsonb which is an array of text conversions). Then you can build an index on the results of this function. Don't forget to declare it immutable.
You will need to unnest the array (essentially normalizing your data model "on-the-fly") then you can use a subquery to check the value:
select t.*
from the_table t
where exists (select *
from jsonb_array_elements(t.data -> 'points') as x(element)
where (x.element ->> 'id')::int in (select id
from other_table))

How can I do less than, greater than in JSON array object Postgres fields? But performance is much better required

I want to retrieve data by specific field operation it store array of object. i want to add new object in it.
CREATE TABLE justjson ( id INTEGER, doc JSONB);
INSERT INTO justjson VALUES ( 1, '[
{
"name": "abc",
"age": "22"
},
{
"name": "def",
"age": "23"
}
]');
retrieve data where age is greater then and equal to 23 how is possible
And i have solution for such thing but it decrease query performance to much.
my solutions is
using jsonb_array_elements:
t=# with a as (select *,jsonb_array_elements(doc) k from justjson)
select k from a where (k->>'age')::int >= 23;
k
------------------------------
{"age": "23", "name": "def"}
(1 row)
I need a solution or other thing by which i do such thing with high performance.

Using LIKE operator for array of objects inside jsonb field in PostgreSQL

Is it possible to use LIKE operator for single key/value inside array of objects for jsonb field in PostgreSQL 9.4? For example I have:
id | body
------------------------------------------------------------
1 | {"products": [{"name": "qwe", "description": "asd"}, {"name": "zxc", "description": "vbn"}]}
I know, I can get a product with something like this:
select * from table where 'body'->'products' #> '[{"name": "qwe"}]'::jsonb
The question is: can I get this product if I don't know full name of it?
Try to get the key and value by using jsonb_each() function:
WITH json_test(data) AS ( VALUES
('{"products": [{"name": "qwe", "description": "asd"}, {"name": "zxc", "description": "vbn"}]}'::JSONB)
)
SELECT doc.key,doc.value
FROM json_test jt,
jsonb_array_elements(jt.data->'products') array_elements,
jsonb_each(array_elements) doc
WHERE
doc.key = 'name'
AND
doc.value::TEXT LIKE '%w%';
Output will be the following:
key | value
------+-------
name | "qwe"
(1 row)