N1QL join with same Bucket with some logic - couchbase

I have below json.
First Campaign
"campaign|1000":{
"_id": 1000,
"_type": "Campaign",
"country": 14,
"created": "2016-03-08T18:30:00.000Z",
"user": 45
"bids":[{
click:123
},
{
click:50
}
]
}
second USER
"User|257"{
"IMId": "",
"IMType": 0,
"_id": 257,
"_type": "User",
"children:[1,4,45,67,106]
"roles":[4]
"email": "krishn#inheritx.com",
}
Now I need to join this json base on who has roles=[4] and join it children with campaign. here children is user like child 45 means "User|45"
I am trying below query
select Users._id,count(Campaign._id) total from Inheritx Campaign
join Inheritx Users on keys("User|"|| TOSTRING(Campaign.`user`))
join reachEffect realted_users on keys ARRAY "User|" || TOSTRING FOR
c IN Users.children END where Campaign._type="Campaign" and
Users.roles=[4] group by Users._id
But I need to join with campaign and children of user whose users has roles is 4
I need output like below
{
user:257
clicks:157
}

Two options.
(1) You can start with campaign, join to users, and then filter on roles afterwards.
(2) You can start with users, filter on roles, and then use an INDEX JOIN to join users to campaigns.
See https://dzone.com/articles/join-faster-with-couchbase-index-joins

Related

Get specific data from MYSQL using PHP

I have two tables as follows
user table
user_id
name
1
zia
2
john
3
raza
subject table
data_id
user_id
subject
1
1
Math
2
1
Chem
3
1
Bio
4
2
Math
5
2
Phy
when I am querying data i am getting results like this:
[
{
"user_id": "1",
"name": "zia",
"subject": [
"Math",
"Chem",
"Bio"
]
},
{
"user_id": "2",
"name": "john",
"subject": [
"Math",
"Phy"
]
},
]
My query is as follows
SELECT
users.user_id,
users.name,
GROUP_CONCAT(subjects.subject) sub
FROM
`users`
INNER JOIN subjects ON users.user_id = subjects.user_id
GROUP BY
subjects.user_id;
but actually I want to get data in following way:
the resuluts shown above are in such a way that if an entry from user table does not have coresponding enteries in subject table even then we must have user name and user id in our rsults as follows
[
{
"user_id": "1",
"name": "zia",
"subject": [
"Math",
"Chem",
"Bio"
]
},
{
"user_id": "2",
"name": "john",
"subject": [
"Math",
"Phy"
]
},
{
"user_id": "3",
"name": "Raza",
}
]
Here as you see that we have data in such a way that all the enteries from user table are shown alog with subject enteries from subject table if they match otherwise every user table entery is showing up with no affect.
*PLease help me in solving this issue **
You probably need to use LEFT JOIN instead of INNER JOIN, because you want to retrieve user without subject too

AWS IoT Core sql query rule - Comparing 2 object arrays returns null/undefined?

I'm trying to compare 2 arrays in a sql query. Everything seems to work fine while getting data from dynamodb and MQTT broker server.
But if I try to compare both arrays, doesn't return anything or its undefined.
My sql query:
SELECT ts, objects, (SELECT id FROM get_dynamodb('table', 'key_name', 'key_value', 'rolearn').ids) AS db, (SELECT id from objects) as obj_ids
FROM 'subscribed/topic'
WHERE objects <> []
Result:
{
"ts": 1615807935588,
"objects": [
{
"id": 1,
"planet": "jupiter"
},
{
"id": 2,
"planet": "mars"
},
],
"db": [
{
"id": 2
},
{
"id": 3
}
],
"obj_ids": [
{
"id": 1
},
{
"id": 2
}
]
}
So far it's ok, now all I want to do is compare if "obj_ids" and "db" arrays are different (obj_ids <> db), and by the aws documentation https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-operators.html#iot-sql-operators-not-eq I can compare both arrays.
So if I do:
SELECT ts, objects, (SELECT id FROM get_dynamodb('table', 'key_name', 'key_value', 'rolearn').ids) AS db, (SELECT id from objects) as obj_ids
FROM 'subscribed/topic'
WHERE objects <> []
AND obj_ids <> db
The code doesn't return anything. I've already tested comparing 2 objects arrays hardcoded into the query and it works just has I intended.
SELECT ([{"id": 1},{"id": 2}] <> [{"id": 1}]) as result
FROM 'subscribed/topic'
Result:
{
"result": true
}
Any response will be appretiated.
Thanks!
Credits from Ben T
As AWS Docs WHERE clause says:
"you cannot reference any aliases created with the AS keyword in the SELECT. The WHERE clause is evaluated first, to determine if SELECT is evaluated."
So all I needed to do is move the (SELECT id FROM get_dynamodb('table', 'key_name', 'key_value', 'rolearn').ids) and (SELECT id from objects) to the WHERE clause.
Final query:
SELECT ts, objects
FROM 'subscribed/topic'
WHERE objects <> []
AND (SELECT id from objects) <> (SELECT id FROM get_dynamodb('table', 'key_name', 'key_value', 'rolearn').ids)

NEST in COUCHBASE

How to nest data in couhcbase similar to mongo DB we do on reference key.
we have two table In a bucket first table is "CHAIN", and second table is "STORE".
I am MONGO user previously and very new to couchbase.
Please suggest how I can nest using N1QL for couchbase
Table 1 CHAIN
{
"chId": "chid_1",
"chName": "Walmart",
"type": "CHAIN"
}
2nd table STORE
{
"chId": "chid_1",
"csName": "store1",
"type": "STORE"
}
{
"chId": "chid_1",
"csName": "store2",
"type": "STORE"
}
I want to get data by joing these table as
{
"chId": "chid_1",
"chName": "Walmart",
"type": "CHAIN",
"stores": [
{"csName": "store1", "type": "STORE"},
{"csName": "store2", "type": "STORE"}]
}
Use JOIN, GROUP BY. Also checkout https://blog.couchbase.com/ansi-join-support-n1ql/
CREATE INDEX ix1 ON (chId) WHERE type = "CHAIN";
CREATE INDEX ix2 ON (chId) WHERE type = "STORE";
SELECT c.*, ARRAY_AGG({s.type, s.csName}) AS stores
FROM default AS c
JOIN default AS s ON c.chId = s.chId
WHERE c.type = "CHAIN" AND s.type = "STORE"
GROUP BY c;
You Can also use ANSI NEST if you want include whole document
SELECT c.*, s AS stores
FROM default AS c
NEST default AS s ON c.chId = s.chId AND s.type = "STORE"
WHERE c.type = "CHAIN";

Count occurences along with result using DISTINCT ON on PostgreSQL

I have data like this:
[
{"name": "pratha", "email": "p#g.com", "sub": { "id": 1 } },
{"name": "john", "email": "x#x.com", "sub": { "id": 5 } },
{"name": "pratha", "email": "c#d.com", "sub": { "id": 2 } }
]
This is my query to get unique and latest emails:
SELECT DISTINCT ON (jae.e->>'name')
jae.e->>'name' as name,
jae.e->>'email' as email
FROM survey_results sr
CROSS JOIN LATERAL jsonb_array_elements(sr.data_field) jae (e)
ORDER BY jae.e->>'name', jae.e->'sub'->>'id' desc
Problem is, when I add count(*) to select, all counts are equal.
I want to get unique result with distinct, and count their occurrences. So in this case, pratha should be 2 and john should be 1
with their data (not just counts)
How can achieve this with PostgreSQL?
See here: https://dbfiddle.uk/?rdbms=postgres_11&fiddle=f5c640958c3e4d594287632d0f4a835f
Do you need this?
SELECT DISTINCT ON (jj->>'name') jj->>'name', jj->>'email' , count(*) over(partition by jj->>'name' )
from survey_results
join lateral jsonb_array_elements(data_field) j(jj) on true
ORDER BY jj->>'name', jj->'sub'->>'id' desc
https://dbfiddle.uk/?rdbms=postgres_11&fiddle=5f07b7bcb0001ebe32aa2f1338d9d0f0

Unnest and Average operation in Couchbase

I have following structure saved in a bucket:
[
{
"Grouplens_1M": {
"genres": [
"Thriller",
"Drama"
],
"movieId": 3952,
"ratings": [
{
"rating": 4,
"userId": 23
},
{
"rating": 5,
"userId": 36
},
{
"rating": 4,
"userId": 52
}
],
"title": "Contender, The (2000)"
}
}
]
Now I need to get all titles which are rated in average above 3. I found out, that I need to unnest ratings and then use AVG to get the average. But it was not working. After trying to figure out how to solve this problem, I came to this:
SELECT g.title, AVG(r_item.rating) AS avg_r
FROM Grouplens_1M AS g
UNNEST ratings r_item
WHERE r_item > 4.0
GROUP BY g.title
After execution time on the query, it shows me a result. But the WHERE clause is not correct. It seems to ignore the statement as it shows me all movies with the average rating.
Since you want to filter out results based on the value of the derived average use HAVING. WHERE would be used to limit the documents considered for the query.
Try
SELECT g.title, avg_r
FROM Grouplens_1M AS g
UNNEST ratings r_item
GROUP BY g.title
LETTING avg_r = AVG(r_item.rating)
HAVING avg_r > 4.0;