OrientDB - index of one record in select results - orientdb

Can without scripts language get record position in select resutls set?
For example, i have some mySelect select with results:
[{ ..., value: 1 }, { '#rid': '#9:1', value: 2 }, { ..., value: 3 }]
Any i want to get index of #9:1 some how like that (pseudo code):
select indexOf('#9:1') from (mySelect)
or
select indexOf(select from (mySelect) where #rid='#9:1')
Needed result:
1

You can retrieve the position of a substring by querying a string (JSON) resultset as such:
SELECT #this.toJSON().indexOf("#9:1") FROM mySelect WHERE #rid = #9:1
For reference, check out the documentation. I hope this helps.

Related

Extracting all keys from a JSON object unless a certain key has a value

My Postgres jsonb-foo isn't that great but I'd appreciate some help with a query I am trying to put together.
I have this rudimentary query to extract the name of all keys in the _doc's 'answers' key. The jsonb data looks something like this
_doc = {
"answers": {
"baz": true,
"qux": true
"other": "How do i find this"
}
}
and a query might look this this:
SELECT ss.foo, count(DISTINCT (ss.bar)) FROM (
SELECT (_doc::jsonb -> 'bar')::text as bar,
jsonb_object_keys(_doc::jsonb -> 'answers' -> 'foo') as foo
FROM public."table_name"
) ss
WHERE ss.foo IS NOT NULL
GROUP BY ss.foo;
So really the output here would be the number of times each key of answers appears.
("baz" = 1, "qux" = 1, "other" = 1)
Here is my problem, I want to get the number of times each key appears, apart from in the case of other. In that case I want to get the number of times its contents appears. So I want the result to be
("baz" = 1, "qux" = 1, "How do i find this" = 1)
If possible I would love some help structuring this query.
Thank you
demo:db<>fiddle for several json records
demo:db<>fiddle for one json records which has the same key twice (strictly not recommended!)
Using the json_each_text() function to get the key/value pairs. After that take the keys or the value of other, selecting through a CASE clause
SELECT
CASE WHEN elems.key = 'other' THEN elems.value
ELSE elems.key
END AS key,
COUNT(*)
FROM data,
json_each_text(jsondata -> 'answers') AS elems
GROUP BY 1

Json_query check which rows have a special value in their json list

I have a table that each row contains a json column. Inside the json column I have an object containing an array of tags. What I want to do is to see which rows in my table have the tag that I am searching for.
Here is an example of my data:
Row 1:
Id :xxx
Jsom Column:
{
"tags":[
{"name":"blue dragon", weight:0.80},
{"name":"Game", weight:0.90}
]
}
Row 2:
Id : yyy
Jsom Column:
{
"tags":[
{"name":"Green dragon", weight:0.70},
{"name":"fantasy", weight:0.80}
]
}
So I want to write a code that if I search for Green, it returns only row 2 and if I search for dragon it returns both row 1 and 2. How can I do that?
I know I can write this to access my array, but more than that I am clueless :\
I am looking for something like this
Select * from myTable
where JSON_query([JsonColumn], '$.tags[*].name') like '%dragon%'
update
My final query looking like this
select DISTINCT t.id, dv.[key], dv.value
from #t t
cross apply openjson(doc,'$.tags') as d
where json_Value( d.value,'$.name') like '%dragon%'
Something like this:
declare #t table(id int, doc nvarchar(max))
insert into #t(id,doc) values
(1,'
{
"tags":[
{"name":"blue dragon", "weight":"0.80"},
{"name":"Game", "weight":"0.90"}
]
}'),(2,'
{
"tags":[
{"name":"Green dragon", "weight":"0.70"},
{"name":"fantasy", "weight":"0.80"}
]
}')
select t.id, dv.[key], dv.value
from #t t
cross apply openjson(doc,'$.tags') as d
cross apply openjson(d.value) dv
where dv.value like '%dragon%'

PostgreSQL Nesting a Select and returning the nested data

I have a database with 3 tables looking like this:
product_types
id label assignments
1 Shirt [{"default":true, "assignment": 1}]
assignments
id label assignments
1 Shirt Options [{"label":"Size", "option":8}]
options
id label choices
8 Sizing [{"label":"Small"}, {"label":"Medium"}]
I'm trying to write a query to return an aggregate collection of the data like this. The 2 assignments tables are jsonb and the choices table is also jsonb
{
label: "Shirt"
assignments: [
{
default: true,
assignment: 1
values: [
{
label: "Size",
option: 8,
choice_values: {
id: 8,
label: "Sizing",
choices: [{label: "Small", {label: "Medium"}]
}
}
]
}
]
}
As you can see it contains both nested arrays and nested objects, this is the query I have so far.
SELECT *,
(SELECT json_agg(assignments.*) FROM assignments WHERE assignments.id=1) AS assigned,
(SELECT json_agg(options.*) FROM options WHERE options.id=8) AS options
FROM product_types
WHERE id=${req.body.id}
The problem is I can't figure out how to get the actual ID values based on the inner jsonb array data. As well as the above query doesn't nest the values but creates a separate array.
Here it is: http://sqlfiddle.com/#!17/037b2b/1
SELECT jsonb_build_object(
'label', product_types.label,
'assignments', (SELECT jsonb_agg(jsonb_set(product_types_assignments, '{values}', a.a)) FROM (
SELECT product_types_assignments,
(
SELECT jsonb_agg(jsonb_set(assignments_assignments, '{choice_values}', to_jsonb(options.*)))
FROM jsonb_array_elements(assignments.assignments) assignments_assignments
JOIN options ON (assignments_assignments->>'option')::int = options.id
) as a
FROM jsonb_array_elements (product_types.assignments) product_types_assignments
JOIN assignments ON (product_types_assignments->>'assignment')::int = assignments.id
) a)
)
FROM product_types

Postgresql jsonb traversal

I am very new to the PG jsonb field.
I have for example a jsonb field containing the following
{
"RootModule": {
"path": [
1
],
"tags": {
"ModuleBase1": {
"value": 40640,
"humanstring": "40640"
},
"ModuleBase2": {
"value": 40200,
"humanstring": "40200"
}
},
"children": {
"RtuInfoModule": {
"path": [
1,
0
],
"tags": {
"in0": {
"value": 11172,
"humanstring": "11172"
},
"in1": {
"value": 25913,
"humanstring": "25913"
}
etc....
Is there a way to query X levels deep and search the "tags" key for a certain key.
Say I want "ModuleBase2" and "in1" and I want to get their values?
Basically I am looking for a query that will traverse a jsonb field until it finds a key and returns the value without having to know the structure.
In Python or JS a simple loop or recursive function could easily traverse a json object (or dictionary) until it finds a key.
Is there a built in function PG has to do that?
Ultimately I want to do this in django.
Edit:
I see I can do stuff like
SELECT data.key AS key, data.value as value
FROM trending_snapshot, jsonb_each(trending_snapshot.snapshot-
>'RootModule') AS data
WHERE key = 'tags';
But I must specify the the levels.
You can use a recursive query to flatten a nested jsonb, see this answer. Modify the query to find values for specific keys (add a condition in where clause):
with recursive flat (id, path, value) as (
select id, key, value
from my_table,
jsonb_each(data)
union
select f.id, concat(f.path, '.', j.key), j.value
from flat f,
jsonb_each(f.value) j
where jsonb_typeof(f.value) = 'object'
)
select id, path, value
from flat
where path like any(array['%ModuleBase2.value', '%in1.value']);
id | path | value
----+--------------------------------------------------+-------
1 | RootModule.tags.ModuleBase2.value | 40200
1 | RootModule.children.RtuInfoModule.tags.in1.value | 25913
(2 rows)
Test it in SqlFiddle.

OrientDB - Creating an edge using rid's from index queries

I'm trying to create edges between existing vertices queried by their indexed IDs, similar to the first answer here, but using this index lookup query instead of the label query:
CREATE EDGE cite
FROM
(SELECT FROM index:<className>.<indexName> WHERE key = "<keyString>")
TO
(SELECT FROM index:<className>.<indexName> WHERE key = "<keyString>")
This gives me the following error: com.orientechnologies.orient.core.exception.OCommandExecutionException: Source vertex '#-1:-1' not exists
Possibly relevant:
When I just query SELECT FROM index:<className>.<indexName> WHERE key = "<keyString>" by itself it returns an array object structured like:
[ { '#type': 'd',
key: '<keyString>',
rid: { cluster: <actual cluster>, position: <actual position> }
#rid: { cluster: -1, position: -1 } } ]
I'm guessing that the error has something to do with the CREATE EDGE query using the #rid instead of the rid but I'm not sure.
The query successfully creates the edges if I simply use the #<actual cluster>:<actual position> instead of the SELECT subquery.
Any ideas what I might be doing wrong?
Edit: In the interest of replicability, I have the same problem in the GratefulDeadConcerts database when I (1) add a property name to the V class schema, (2) create a unique nameIndex index of V using the name property under V, and then (3) use the following query:
create edge followed_by from (select from index:nameIndex where key = 'HEY BO DIDDLEY') to (select from index:nameIndex where key = 'IM A MAN')
Why don't you query the class directly?
CREATE EDGE cite
FROM
(select from Class where field = '<keyString>')
TO
(select from Class where field = '<keyString>')
Select from index return a temp document as result set with key,and rid
you can try but i don't know if it will work
SELECT expand(rid) FROM index:<className>.<indexName> WHERE key = "<keyString>"