How to find all property names of label on AgensGraph? - agens-graph

I want to find all property names of specific label on AgensGraph.
Which command am I use?

There is no command to find property names.
But, you can use function "jsonb_object_keys" for it.
agens=# create (:v1{key:1,value:2});
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 0)
agens=# create (:v1{id:1,text:'value'});
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 0)
agens=# match (n:v1) return distinct jsonb_object_keys( properties(n) );
jsonb_object_keys
-------------------
"text"
"id"
"value"
"key"
(4 rows)

Related

SQL Server oddity with full-text indexing and case sensitivity and numbers

This problem may be unique to our server, but I can't tell from the symptoms where the issue may lie.
I have a field (searchtitle) in a table (fsItems) that has a full-text index turned ON. For the record with primary key (IDItem) 704629 the content of this field is "TEST AFA 0 TEST".
Surprisingly, the following query returns no results:
SELECT * FROM fsItems WHERE CONTAINS(searchtitle,'AFA') AND IDItem = 704629
However, if I change the content to be "TEST afa 0 TEST" or "TEST AFA O TEST" (capital "O" instead of zero) the query returns the record. (It also returns the record if I change the content to "TEST AFB 0 TEST" and the CONTAINS argument to 'AFB'.)
At first I thought maybe AFA was some kind of stop word, but that wouldn't explain why changing zero to upper-case "O" returns the proper result.
Any idea what is going on here?
Thanks for any suggestions
Very interesting little quirk. It appears SQL Server is considering "AFA 0" as a single "word". My guess is this is an issue with the word breakers configured for standard English. It appears you can manually adjust them, but it doesn't look simple or intuitive. See Microsoft's how to documentation here
Identifying Words in Full-text Index
The below script lists every word in a full text index. If you run this against your table, you'll see in column display_term word "AFA 0". Side note: this script is also very useful in optimizing full text indexes by identifying "noisy" words to add to your stop list
Select *
From sys.dm_fts_index_keywords(Db_Id(),Object_Id('dbo.tbl_fulltext_test') /*Replace with your table name*/)
Order By document_count Desc
Full SQL Used to Identify the Issue
CREATE TABLE tbl_fulltext_test
(ID int constraint PK_fulltext_test primary key identity (1,1)
,String Varchar(1000)
)
Create Fulltext Catalog ct_test
With Accent_Sensitivity = Off
Create Fulltext Stoplist sl_test
From System Stoplist;
Create Fulltext Index On tbl_fulltext_test(String)
Key Index PK_fulltext_test On ct_test
With Stoplist = sl_test,Change_Tracking Auto;
INSERT INTO tbl_fulltext_test
VALUES
('TEST AFA 0 TEST') /*Zero*/
,('TEST afa 0 TEST') /*Zero*/
,('TEST AFB 0 TEST') /*AFB*/
,('TEST AFA O TEST') /*Letter O*/
/*Returns rows 2 and 4*/
SELECT *
FROM tbl_fulltext_test
WHERE CONTAINS (String,'AFA')
/*Returns row 1*/
SELECT *
FROM tbl_fulltext_test
WHERE CONTAINS (String,'"AFA 0"')

Is it possible to add a constraint to check every inserted object into a JSON array using Postgres?

I am trying to figure out how to add a constraint to my table that contains a JSON object in Postgres. I would like that constraint to make sure a jpg will have a non null md5 property.
I have tried to check the subarray but I cannot get it to work on an array. I can test the property if use the dereferencing arrow operator (table->'jpg'->0 ? 'md5'). I have tried to use the jsonb_array_elements() function as well but it is not allowed inside a constraint statement.
For instance:
{
jpg: [
{
md5: "some md5",
...
}
]
}
I would use this:
ALTER TABLE table ADD CONSTRAINT md5_is_defined CHECK(table->'jpg'->0 ? 'md5')
But I don't want to check just the first inserted element
I would like to know if there is some trick to use jsonb_array_elements in this check statement. And yes I realize I should normalize my data. I tried to do this but it became a monstrosity to write the statements for.
Arrays are extremely cumbersome to deal with in SQL as they basically violate anything that SQL does. Checking every element in an array for the presence of something is typically a strong indication that an array was the wrong choice to begin with.
With Postgres 12 this is extremely easy to do:
alter table the_table
add constraint md5_is_defined
check (jsonb_path_exists(the_column, '$.jpg[*].md5'));
For older versions, the only thing I can think of is to create a function that checks the presence and then use that function in the check constraint:
create or replace function check_md5(p_input jsonb)
returns boolean
as
$$
select exists (select *
from jsonb_array_elements(p_input -> 'jpg') as t(e)
where e ? 'md5');
$$
language sql
immutable;
Then you can use it like this:
alter table the_table
add constraint md5_is_defined
check (check_md5(the_column));
Edit
To check if a specific key contains a non-empty array you can use something like this:
alter table the_table
add constraint non_empty_array
check (jsonb_path_exists(the_column, '$.event ? (#.teams.type() == "array" && #.teams.size() > 0)'));
The check for #.teams.type() == "array" is necessary because a simple {"teams": "yes"} also returns a non-zero value for size()

Unable to access graph after re-login

I created graph on AgensGraph.
$ agens
agens (AgensGraph 2.1.0, based on PostgreSQL 10.4)
Type "help" for help.
agens=# create graph g;
CREATE GRAPH
agens=# create (:v{id:1});
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 0)
agens=# \q
$ agens
agens (AgensGraph 2.1.0, based on PostgreSQL 10.4)
Type "help" for help.
agens=# match (n) return n;
ERROR: graph_path is NULL
HINT: Use SET graph_path
agens=# \q
But, unable to access graph after re-login.
How to access graph after re-login
Use "ALTER USER ... SET GRAPH_PATH TO ..." statement for set default graph on login.
$ agens
agens (AgensGraph 2.1.0, based on PostgreSQL 10.4)
Type "help" for help.
agens=# create graph g;
CREATE GRAPH
agens=# alter user agens set graph_path to g;
ALTER ROLE
agens=# create (:v{id:1});
GRAPH WRITE (INSERT VERTEX 1, INSERT EDGE 0)
agens=# \quit
After changing "GRAPH_PATH", You can access to your graph.
$ agens
agens (AgensGraph 2.1.0, based on PostgreSQL 10.4)
Type "help" for help.
agens=# match (n) return n;
n
-----------------
v[3.1]{"id": 1}
(1 row)

How to load file on AgensGraph?

I tried to load comma separated file on agensgraph.
But agensgraph does not have load utility on package.
How can I load file on agensgraph?
You can use "Foreign Data Wrapper", Instead of utility.
First, create file few extension.
agens=# CREATE EXTENSION file_fdw;
CREATE EXTENSION
Second, create server object.
agens =# CREATE SERVER graph_import FOREIGN DATA WRAPPER file_fdw;
CREATE SERVER
Next, create foreign table with file.
agens =# CREATE FOREIGN TABLE fdwSample
agens-# (
agens(# id INT8,
agens(# name VARCHAR(256)
agens(# )
agens-# SERVER graph_import
agens-# OPTIONS
agens-# (
agens(# FORMAT 'csv',
agens(# HEADER 'false',
agens(# DELIMITER ',',
agens(# NULL '',
agens(# FILENAME 'sample.dat'
agens(# );
CREATE FOREIGN TABLE
Last, load file use "LOAD" clause.
agens=# LOAD FROM fdwSample AS sample
agens-# CREATE (:node {id:sample.id,name:sample.name});
GRAPH WRITE (INSERT VERTEX 2, INSERT EDGE 0)
After all, you can find loaded data.
agens =# MATCH (n:node) RETURN n;
n
-------------------------------------
node[3.1]{"id": 1, "name": "steve"}
node[3.2]{"id": 2, "name": "bill"}
(2 rows)
Good luck.

How to use FULL-TEXT SEARCH in H2 Database?

Consider the following example
CREATE ALIAS IF NOT EXISTS FT_INIT FOR "org.h2.fulltext.FullText.init";
CALL FT_INIT();
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR);
INSERT INTO TEST VALUES(1, 'Hello World');
CALL FT_CREATE_INDEX('PUBLIC', 'TEST', NULL);
and i have executed the following query
SELECT * FROM FT_SEARCH('Hello', 0, 0);
But this query is returning "PUBLIC"."TEST" WHERE "ID"=1 .
Do i have to again execute this "PUBLIC"."TEST" WHERE "ID"=1 to get the record containing 'Hello' word ?
What is the query to search all records with 'ell' word in them from the FT_Search. such as like %ell% in H2 Native Full-Text Search
Yes, each row in a query using FT_SEARCH represents a schema-table-row where one of the key words was found. The search is case insensitive, and the text parameter to FT_SEARCH may include more than one word. For example,
DELETE FROM TEST;
INSERT INTO TEST VALUES(1, 'Hello World');
INSERT INTO TEST VALUES(2, 'Goodbye World');
INSERT INTO TEST VALUES(3, 'Hello Goodbye');
CALL FT_REINDEX();
SELECT * FROM FT_SEARCH('hello goodbye', 0, 0);
returns only row three:
QUERY SCORE
"PUBLIC"."TEST" WHERE "ID"=3 1.0
Also note that FT_SEARCH_DATA may be used to retrieve the data itself. For example,
SELECT T.* FROM FT_SEARCH_DATA('hello', 0, 0) FT, TEST T
WHERE FT.TABLE='TEST' AND T.ID=FT.KEYS[0];
returns both rows containing the keyword:
ID NAME
1 Hello World
3 Hello Goodbye
Apache Lucene supports wildcard searches, although leading wildcards (e.g. *ell) tend to be expensive.
Do i have to again execute this "PUBLIC"."TEST" WHERE "ID"=1 to get the record containing 'Hello' word ?
Yes, except if you use a join as described by trashgod. The reason is: usually rows are much larger than just two words. For example, a row contains a CLOB with a document. If the result of the fulltext search would contain the data, then fulltext search would be much slower.
What is the query to search all records with 'ell' word in them from the FT_Search. such as like %ell% in H2 Native Full-Text Search
The native fulltext search can't do that directly. The reason is: fulltext search only indexes whole words. (By the way: does Google support searches if you only know a part of a word? Apache Lucene does support it) Actually, for H2, there would be a way: first, search the words table (FT.WORDS) for matches, and then use a regular search.

Resources