Stratio Lucene Index 3.0.9: Purpose of INet mapper - lucene

From the docs for the Stratio Lucene Index Plugin, the INet mapper looks interesting but there's not a lot of motivation behind it: ie. https://github.com/Stratio/cassandra-lucene-index/blob/branch-3.0.9/doc/documentation.rst#inet-mapper.
Given that it represents an IP address (typed) and is therefore distinct from being simple a string, what sort of queries can I apply to it? In particular, is it possible to do a ranged query on it?

Lucene index inet mapper is intended to map CQL inet data type. The only advantage on it is to make parsing more flexible. For example, given the following data:
CREATE TABLE t (
pk int PRIMARY KEY,
address inet
) ;
CREATE CUSTOM INDEX i ON t ()
USING 'com.stratio.cassandra.lucene.Index'
WITH OPTIONS = {
'refresh_seconds': '1',
'schema': '{
fields : {
address : {type: "inet"},
address_s : {type: "string", column: "address"}
}
}'};
INSERT INTO t(pk, address) VALUES (0, '::FFFF:8:8:8');
All these queries will found the indexed row:
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address", value: "::ffFF:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address", value: "::0:ffff:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address", value: "0:0:0:0:ffff:8:8:8"}}');
However, the same queries wouldn't work with a string mapper:
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address_s", value: "::ffFF:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address_s", value: "::0:ffff:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"match", field:"address_s", value: "0:0:0:0:ffff:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"wildcard", field:"address_s", value: "*:8:8:8"}}');
Aside from this, the generated Lucene field is a string field, so there is no special treatment for wildcard or range queries, that should use the expanded format of the IP address and will have a lexicographical behaviour:
SELECT * FROM t WHERE expr(i, '{filter:{type:"wildcard", field:"address", value: "*:8:8:8"}}');
SELECT * FROM t WHERE expr(i, '{filter:{type:"range", field:"address", lower: "::FFFF:8:8:7"}}');

Related

Trying to filter a SQL query on a JSON field

I have 4 tables in PostgreSQL:
HomeSearch(id, client_id, name)
HomeSearchNote(id, homesearch_id, text)
Client(id, user_id)
User(id)
I'm trying to query HomeSearch and return a JSON as follows but only for those entries in HomeSearch for which the Client.user_id is equal to a certain value (say, 100):
HomeSearch {
id:
name:
client: {
id:
user: {
id
}
}
notes: [{
id:
homesearch_id:
text:
},
...]
}
My SQL statement is:
SELECT
*,
( SELECT row_to_json(client) from client where homeSearch.client_id=client.id ) client,
( SELECT json_agg(row_to_json(homeSearchNote)) from homeSearchNote where homeSearchNote.homesearch_id=homeSearch.id) notes
FROM homeSearch
WHERE client->>'user_id'=100
LIMIT 5;
However, this returns:
ERROR: column "client" does not exist
LINE 19: WHERE client->>user_id=100
If I run the query without the WHERE clause in PGAdmin, I can clearly see a table with a 'client' column of type JSON.
Can anyone comment what would be the right way to place / write the WHERE clause ?
Much appreciated!
On way you can re-write the sql is as
With a as
(SELECT *,
( SELECT row_to_json(client) from client where homeSearch.client_id=client.id ) client,
( SELECT json_agg(row_to_json(homeSearchNote)) from homeSearchNote where homeSearchNote.homesearch_id=homeSearch.id) notes
FROM homeSearch
)
Select * from a WHERE client->>'user_id'=100
LIMIT 5;

BigQuery select expect double nested column

I am trying to remove a column from a BigQuery table and I've followed the instructions as stated here:
https://cloud.google.com/bigquery/docs/manually-changing-schemas#deleting_a_column_from_a_table_schema
This did not work directly as the column I'm trying to remove is nested twice in a struct. The following SO questions are relevant but none of them solve this exact case.
Single nested field:
BigQuery select * except nested column
Double nested field (solution has all fields in the schema enumerated, which is not useful for me as my schema is huge):
BigQuery: select * replace from multiple nested column
I've tried adapting the above solutions and I think I'm close but can't quite get it to work.
This one will remove the field, but returns only the nested field, not the whole table (for the examples I want to remove a.b.field_name. See the example schema at the end):
SELECT AS STRUCT * EXCEPT(a), a.* REPLACE (
(SELECT AS STRUCT a.b.* EXCEPT (field_name)) AS b
)
FROM `table`
This next attempt gives me an error: Scalar subquery produced more than one element:
WITH a_tmp AS (
SELECT AS STRUCT a.* REPLACE (
(SELECT AS STRUCT a.b.* EXCEPT (field_name)) AS b
)
FROM `table`
)
SELECT * REPLACE (
(SELECT AS STRUCT a.* FROM a_tmp) AS a
)
FROM `table`
Is there a generalised way to solve this? Or am I forced to use the enumerated solution in the 2nd link?
Example Schema:
[
{
"name": "a",
"type": "RECORD",
"fields": [
{
"name": "b",
"type": "RECORD"
"fields": [
{
"name": "field_name",
"type": "STRING"
},
{
"name": "other_field_name".
"type": "STRING"
}
]
},
]
}
]
I would like the final schema to be the same but without field_name.
Below is for BigQuery Standard SQL
#standardSQL
SELECT * REPLACE(
(SELECT AS STRUCT(SELECT AS STRUCT a.b.* EXCEPT (field_name)) b)
AS a)
FROM `project.dataset.table`
you can test, play with it using dummy data as below
#standardSQL
WITH `project.dataset.table` AS (
SELECT STRUCT<b STRUCT<field_name STRING, other_field_name STRING>>(STRUCT('1', '2')) a
)
SELECT * REPLACE(
(SELECT AS STRUCT(SELECT AS STRUCT a.b.* EXCEPT (field_name)) b)
AS a)
FROM `project.dataset.table`

Nested search without keys in jsonb in PostgreSql

The question is about selection from JSON in PostgreSQL.
For example, application contains translation data in jsonb:
{
"en":{
"locale":"en",
"title":"Title",
"textShort":"Short text",
"textFull":"Full text"
}
"ru":{
"locale":"ru",
"title":"Заголовок",
"textShort":"Короткий текст",
"textFull":"Подробный текст"
}
}
This query works successfully:
select *
from content_records
where translations::json->'en'->>'title' like '%Title.';
But this query requires information about the locale, but the case is that we don't know anything about locales and search must be done for every locale, for example:
select *
from content_records
where translations::json->'any locale'->>'title' like '%Title.';
In MySQL it works as:
select *
from content_records
where LOWER(JSON_EXTRACT(translations, '$.*.title')) LIKE LOWER(:title);
There is the similar function in PostgreSQL:
json_extract_path, but it requires keywords and you can't miss the key as the symbol * does in MySQL.
The question is - how to do the selection of a nested JSON in this situation?
Unfortunately, in Postgres you have to "unnest" the keys first.
Something like this:
select t.*, cr.translations
from content_records cr
cross join lateral jsonb_object_keys(translations) as t(locale)
where lower(cr.translations -> t.locale ->> 'title') like '%title';
Note that if a title matches in more than one locale, you will get one row for each matching locale. If you don't want that, you can do the following:
select cr.*
from content_records cr
where exists (select *
from jsonb_object_keys(cr.translations) as t(locale)
where lower(cr.translations -> t.locale ->> 'title') like '%title')

Querying for a specific value in a String stored in a database field

{"create_channel":"1","update_comm":"1","channels":"*"}
This is the database field which I want to query.
What would my query look like if I wanted to select all the records that have a "create_channel": "1" and a "update_comm": "1"
Additional question:
View the field below:
{"create_channel":"0","update_comm":"0","channels":[{"ch_id":"33","news":"1","parties":"1","questions ":"1","cam":"1","edit":"1","view_subs":"1","invite_subs":"1"},{"ch_id":"18","news":"1","parties":"1","questions ":"1","cam":"1","edit":"1","view_subs":"1","invite_subs":"1"}]}
How would I go about finding out all those that are subadmins in the News, parties, questions and Cams sections
You can use the ->> operator to return a member as a string:
select *
from YourTable
where YourColumn->>'create_channel' = '1' and
YourColumn->>'update_comm' = '1'
To find a user who has news, parties, questions and cam in channel 33, you can use the #> operator to check if the channels array contains those properties:
select *
from YourTable
where YourColumn->'channels' #> '[{
"ch_id":"33",
"news":"1",
"parties":"1",
"questions ":"1",
"cam":"1"
}]';

Postgres SELECT * FROM Table where array has element

I am using Postgres 9.3.2 to make a database of contacts.
Example: If i have a row in my table that looks something like this.
{
firstName : "First name"
lastName : "Last name"
emails : ["email#one.com", "email#two.com", "email#three.com]
}
PS: firstName, lastName and emails are columns in my db and the value associated is the value for that column for that specific row.
I want to be able to query the db so that if i query for the email "email#four.com" the result is nothing but if i query for "email#two.com" the result will be the above row entry.
I dont think the query
"Select * from contactTable where emails="email#two.com""
will work. instead i want to do something like
"Select * from contactTable where emails contains "email#two.com""
any ideas on how to do this?
"Select * from contactTable where emails contains "email#two.com""
I think you want:
"Select * from contactTable where thejsonfield -> emails
Example setup, after fixing up your totally broken json:
CREATE TABLE contacts AS SELECT '{
"firstName" : "First name",
"lastName" : "Last name",
"emails" : ["email#one.com", "email#two.com", "email#three.com"]
}'::json AS myjsonfield;
The following will work in PostgreSQL 9.4, but unfortunately does not in 9.3 due to the oversight of the missing json_array_elements_text function:
select *
from contacts,
lateral json_array_elements_text(myjsonfield -> 'emails') email
where email = 'email#two.com';
For 9.3, you have to use a clumsier method to scan the json array for matching values:
select *
from contacts,
lateral json_array_length(myjsonfield -> 'emails') numemails,
lateral generate_series(0, numemails) n
WHERE json_array_element_text(myjsonfield -> 'emails', n) = 'email#two.com';
You can't use the simple IN or = ANY constructs because (at this point) PostgreSQL doesn't understand that you might have a json array, so it'll fail with:
regress=> SELECT * FROM contacts WHERE 'email#two.com' = ANY (myjsonfield->'emails');
ERROR: op ANY/ALL (array) requires array on right side
LINE 1: SELECT * FROM contacts WHERE 'email#two.com' = ANY (myjsonfi...
^
as it expects a PostgreSQL array, not a json array, and there's no convenient builtin to turn a json array into a PostgreSQL array yet.
Postgres has support for parsing JSON. Here is documentation: http://www.postgresql.org/docs/9.3/static/functions-json.html. I can't give you more detailed answer since you didn't provide exact data and schema, but it's easy to find the right function in documentation.