Querying sub-sub table in Supabase / Grandchild relationship in JOIN QUERY - javascript

Given the following schema:
CREATE TABLE organization (
org_name text NOT NULL,
PRIMARY KEY (org_name)
);
CREATE TABLE teams (
org_name text NOT NULL,
team_name text NOT NULL,
PRIMARY KEY (org_name, team_name),
FOREIGN KEY (org_name)
REFERENCES organization (org_name)
);
CREATE TABLE projects (
org_name text NOT NULL,
team_name text NOT NULL,
project_name text NOT NULL,
products jsonb,
PRIMARY KEY (org_name, team_name, project_name),
FOREIGN KEY (org_name)
REFERENCES organization (org_name),
FOREIGN KEY (org_name, team_name)
REFERENCES teams (org_name, team_name)
);
I want to query the teams table but also return the products from the projects table. Is there a way to do this?

For single relationships set, then you can do the following (assuming a top-bottom relationship as:
organization -> teams and teams -> projects
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
const { data: ret, error } = await supabase
.from('organization')
.select(`*,
teams(*,
projects(products)
)
`);
console.log(JSON.stringify(ret));
In this case, it would not be possible and you would get the following error:
Could not embed because more than one relationship was found for 'organization' and 'teams'
In this case, you can pick the relationship when calling supabase with either:
teams!projects or teams!teams_org_name_fkey. The former is preferred for most cases.
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
const { data: ret, error } = await supabase
.from('organization')
.select(`*,
teams!projects(*,
projects(products)
)
`);
Output:
[{"org_name":"Contoso","teams":[{"org_name":"Contoso","team_name":"Contoso Café","projects":[{"products":{"Dairy":"latte","coffee":["french press","expresso","cold brew"]}}]}]}]

Related

Find an object in a JSON array in mySQL database using javascript with a filter

In my mysql database I have a model with the current format:
id: text
pokemons: JSON
pc: JSON
Here's one as an example:
{
id: '430368553787719692',
pokemons: '["{\\"name\\":\\"houndoom\\",\\"types\\":[\\"dark\\",\\"fire\\"],\\"stats\\":[75,90,50,110,80,95],\\"moves\\":[{\\"name\\":\\"curse\\",\\"type\\":\\"ghost\\",\\"power\\":null,\\"accuracy\\":null,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"solar-beam\\",\\"type\\":\\"grass\\",\\"power\\":120,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"facade\\",\\"type\\":\\"normal\\",\\"power\\":70,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"odor-sleuth\\",\\"type\\":\\"normal\\",\\"power\\":null,\\"accuracy\\":null,\\"priority\\":0,\\"statChanges\\":null}],\\"sprite\\":\\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/229.png\\",\\"color\\":\\"black\\",\\"isLegendary\\":false,\\"isMythical\\":false}", "{\\"name\\":\\"electivire\\",\\"types\\":[\\"electric\\"],\\"stats\\":[75,123,67,95,85,95],\\"moves\\":[{\\"name\\":\\"light-screen\\",\\"type\\":\\"psychic\\",\\"power\\":null,\\"accuracy\\":null,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"natural-gift\\",\\"type\\":\\"normal\\",\\"power\\":null,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"captivate\\",\\"type\\":\\"normal\\",\\"power\\":null,\\"accuracy\\":100,\\"priority\\":0},{\\"name\\":\\"electroweb\\",\\"type\\":\\"electric\\",\\"power\\":55,\\"accuracy\\":95,\\"priority\\":0}],\\"sprite\\":\\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/466.png\\",\\"color\\":\\"yellow\\",\\"isLegendary\\":false,\\"isMythical\\":false}", "{\\"name\\":\\"exeggcute\\",\\"types\\":[\\"grass\\",\\"psychic\\"],\\"stats\\":[60,40,80,60,45,40],\\"moves\\":[{\\"name\\":\\"absorb\\",\\"type\\":\\"grass\\",\\"power\\":20,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"psychic\\",\\"type\\":\\"psychic\\",\\"power\\":90,\\"accuracy\\":100,\\"priority\\":0},{\\"name\\":\\"worry-seed\\",\\"type\\":\\"grass\\",\\"power\\":null,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"toxic\\",\\"type\\":\\"poison\\",\\"power\\":null,\\"accuracy\\":90,\\"priority\\":0,\\"statChanges\\":null}],\\"sprite\\":\\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/102.png\\",\\"color\\":\\"pink\\",\\"isLegendary\\":false,\\"isMythical\\":false}", "{\\"name\\":\\"voltorb\\",\\"types\\":[\\"electric\\"],\\"stats\\":[40,30,50,55,55,100],\\"moves\\":[{\\"name\\":\\"hidden-power\\",\\"type\\":\\"normal\\",\\"power\\":60,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"eerie-impulse\\",\\"type\\":\\"electric\\",\\"power\\":null,\\"accuracy\\":100,\\"priority\\":0},{\\"name\\":\\"magic-coat\\",\\"type\\":\\"psychic\\",\\"power\\":null,\\"accuracy\\":null,\\"priority\\":4,\\"statChanges\\":null},{\\"name\\":\\"thunder-wave\\",\\"type\\":\\"electric\\",\\"power\\":null,\\"accuracy\\":90,\\"priority\\":0,\\"statChanges\\":null}],\\"sprite\\":\\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/100.png\\",\\"color\\":\\"red\\",\\"isLegendary\\":false,\\"isMythical\\":false}", "{\\"name\\":\\"glastrier\\",\\"types\\":[\\"ice\\"],\\"stats\\":[100,145,130,65,110,30],\\"moves\\":[{\\"name\\":\\"endure\\",\\"type\\":\\"normal\\",\\"power\\":null,\\"accuracy\\":null,\\"priority\\":4,\\"statChanges\\":null},{\\"name\\":\\"stomp\\",\\"type\\":\\"normal\\",\\"power\\":65,\\"accuracy\\":100,\\"priority\\":0,\\"statChanges\\":null},{\\"name\\":\\"close-combat\\",\\"type\\":\\"fighting\\",\\"power\\":120,\\"accuracy\\":100,\\"priority\\":0},{\\"name\\":\\"scary-face\\",\\"type\\":\\"normal\\",\\"power\\":null,\\"accuracy\\":100,\\"priority\\":0}],\\"sprite\\":\\"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/896.png\\",\\"color\\":\\"white\\",\\"isLegendary\\":true,\\"isMythical\\":false}"]',
pc: '[null]'
}
Now, Using the mysql2 npm package I want to get the name of a pokemon, and if it's found, return that pokemon object. I add the pokemons to the database like this:
await (
await con
).query(
`UPDATE profileSchema SET pokemons = JSON_ARRAY_APPEND(pokemons, '$', '${JSON.stringify(
pokemon
)}') WHERE id = '${interaction.user.id}'`
);
How can I search a pokemon by its name where the id is equal to the one i input? Something like SELECT profileSchema WHERE JSON_CONTAINS(pokemons, name) WHERE id = 'id I input'? I am new to sql and any help is appreciated!

i want to send unique records for every user who logs in from a mysql database

i want to send every user who logs in a list of unique records i.e not same records from the database,
for every user i want to skip the records that have already been sent to other signed users.bare with me ,am a beginner,how can i implement such?
here is the code that fetches the records from the database
phrases.findAll({
where: {
userId: user.id,
phraseStatus: 1
},
limit: 10,
offset,
10
})
.then((data) => {
userObj.phrases.push(...data);
return res.status(200).json(userObj);
});
You will need to keep track of what has been sent to other users. I suggest you keep a table like phrases_sent to record what has been sent so far. Add the phrase_id to this new table so you have a relationship.
Take a look at associations in the docs.
You can then query the phrases table by outer joining to your phrases_sent table to return phrases that have not been sent so far.
Something like:
const phrases = await sequelize.models.phrase.findAll({
where: {
'$phrasesSents.phrase_id$': {[Op.is]: null} // query the joined table
},
attributes: ['phrase.phrase'], // the unused phrases
include: [
{
attributes: [],
model: sequelize.models.phrasesSent,
required: false, // specify this is a left outer join
}
],
raw: true,
nest: true
});
Would yield:
SELECT "phrase"."phrase"
FROM "phrases" AS "phrase"
LEFT OUTER JOIN "phrases_sent" AS "phrasesSents" ON "phrase"."id" = "phrasesSents"."phrase_id"
WHERE "phrasesSents"."phrase_id" IS NULL;
I believe doing a LEFT OUTER JOIN has performance benefits over a NOT IN (SELECT ...) style query.

select from where with nested select inside the where using knex and mysql

I have a one to many relationship with two tables. I need to use knex to perform a query where I have a piece of data that is only in one table. The query will use this piece of data to find a foreign key on a similar row to get data from the foreign table. To do this with a standard mysql query, I use:
SELECT
sellers_ID,
sellerName,
sellerUsername,
sellerAvatar,
listingID,
productTitle,
productImage,
averageRating,
reviewerName,
reviewerAvatar,
reviewDate,
reviewRating,
reviewText
FROM
sellers,
reviews
WHERE
reviews.sellers_ID = (SELECT sellerID FROM sellers WHERE listingID = ${id})
AND
sellerID = (SELECT sellerID FROM sellers WHERE listingID = ${id})
listing ID belongs to sellers and does not exist on reviews. I can use the listing ID to find a sellerID on the same row, which has a foreign key in reviews. So then I can get what I need from reviews using this listing ID. I want to use knex to perform the same query, but don't know how to handle the nested promises.
Here is what I have:
const promise4all = Promise.all(
[
knex.select('sellerID').from('sellers').where({ listingID : id })
]
)
knex.select(
'sellers_ID',
'sellerName',
'sellerUsername',
'sellerAvatar',
'listingID',
'productTitle',
'productImage',
'averageRating',
'reviewerName',
'reviewerAvatar',
'reviewDate',
'reviewRating',
'reviewText'
).from(
'sellers',
'reviews'
)
.where({
'reviews.sellers_ID': knex.select('sellerID').from('sellers').where({ listingID : id }),
'sellerID' : knex.select('sellerID').from('sellers').where({ listingID : id })
})
.then( result => {
console.log('knex query result: ', result);
})
.catch( error => {
console.log('knex error: ', error)
})
I've experimented with promisifying the nested select query within the where, but it's not working. I receive this error:
code: 'ER_BAD_FIELD_ERROR',
errno: 1054,
sqlMessage: "Unknown column 'sellers_ID' in 'field list'",
sqlState: '42S22',

how to check polygon contain Point Sequelize and postgres

I am working with nodejs, orm is sequelize, database is postgresql. I want to Get
Polygon from another table and where to Vehicles table
here is the code:
const geoRegion = await models.GeoRegion.find({
where: {
id: id,
},
});
const scooters = await models.Vehicle.findAll({
where: {
$and: models.sequelize.where(models.sequelize.fn('ST_Intersects', geoRegion.polygon, models.sequelize.fn('ST_SetSRID', models.sequelize.fn('ST_MakePoint', models.sequelize.col('lastReportedLocation')), '4326')), true),
},
plain: true,
});
the geoRegion has field polygon, I want to check Vehicles inside the polygon
here is the error:
SELECT * FROM \"Vehicles\" AS \"Vehicle\" WHERE ST_Intersects(\"lastReportedLocation\", \"type\" = 'Polygon' AND \"coordinates\" IN (ARRAY[ARRAY[105.293,21.145],...)
"name": "SequelizeDatabaseError",
"error": "column \"type\" does not exist"
ST_Intersects expects two geometries/geographies as arguments. So, I may guess, your query should look like:
select v.*
from Vehicles v
join geoRegion r
on st_intersects(v.lastReportedLocation, r.polygon)
assuming both fields 'lastReportedLocation' from Vehicles table and 'polygon' of geoRegion table contain valid geometries, that's supposed to give you vehicles within area of interest.

How can I query by sort key in AWS DynamoDB?

I have a database of users, and I'd like to return all users with the last name X. I currently have "last" as the sort key for my table. I'm running the following code, but getting a "Query condition missed key schema element" error.
var params = { TableName: 'Patients',
KeyConditionExpression: '#id = :idNum',
ExpressionAttributeNames: {
'#id': 'last'
},
ExpressionAttributeValues: {
':idNum': 'Test'
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
res.json(data);
}
});
To query you must provide a partition key, so with your table, as it is, your only option would be to do a Scan (which is expensive and almost never recommended).
However you can easily add Global Secondary Indexes to allow you to use another key as your partition.
In this case you can add a GSI with last as your partition key.
Then you would be able to Query the global secondary index (note the IndexName parameter) by last name.
If you want to go the scan route, however, you'll need to use:
docClient.scan({
TableName: 'Patients',
FilterExpression: '#l = :l',
ExpressionAttributeNames: { '#l': 'last' },
ExpressionAttributeValues: { ':l': 'Test' },
Limit: 1
}, (err, data) => { /* callback */ })
Just remember that using scans can get expensive and put a strain on your table quickly (more detail here)
This is not the way DynamoDB/NoSQL should be used. You either create a GSI as thomasmichaelwallace suggested or have the users lastname as partition key too. You can add "ln_" before all of your last name partitionkeys to separte them from your other partition keys. If you had firstname as partitions before your primary key should look like that now:
partition | sort
fn_hans | ln_zimmer
fn_steve | ln_jobs
ln_zimmer | fn_hans
ln_jobs | fn_steve
Now you can query all partition which start with ln_. And yes you are supposed to have douplicate data in noSql. NoSQL Design has some articles about how to design a dynamoDB table.

Categories