POSTGRES check if a provided value is present in the column of type array - postgresql

I am trying to check whether a value if present in the column, which is of type array(column_name text[]).
As a server i am using hapi and trying to check the same from hapi through query.
Query which i have written is(query is not working):
where: { column_name: { $in: { provided_value} }}
The column contains the values as:
{1234, 3456}
The values are of type text.
Can someone please help me to identify the issue.
Thanks in advance.

Sequelize does not support this use of ANY, they seem to only support its use like IN.
Instead, you should try the contains operator (#>):
import {Op} from "sequelize";
MyModel.findAll({
where: {
column_name: {
[Op.contains]: [provided_value]
}
}
});
This will generate something like
SELECT * FROM "MyModel" WHERE column_name #> '{"provided_value"}';

Related

sequelize, query property on array of objects

I have looked extensively for an answer but could not find a simple solution.
I have a table that contains a column subscriptionHistory
The data can look like so:
[
{
"fromDate": "2023-01-24T10:11:57.150Z",
"userSubscribedToo": "EuuQ13"
},
{
"fromDate": "2022-01-24T10:11:57.150Z",
"tillDate": "2022-02-24T22:59:59.999Z",
"userSubscribedToo": "a4ufoAB"
}
]
I'm trying to find the records of the subscriptions.
In Mongo we do
'subscriptionHistory.$.userSubscribedToo' = 'a4ufoAB'
Nice and easy.
I'm using PostgreSQL and Sequelize,
The following doesn't work.
const totalEarnings = await SubscriptionToken.count({
where: {
'subscriptionHistory.$.userSubscribedToo': user.id,
},
});
Neither do any direct queries
SELECT *
FROM vegiano_dev."subscription-tokens"
WHERE "subscriptionHistory"->>'userSubscribedToo' = 'a4ufoAB'
--WHERE "subscriptionHistory" #> '{"userSubscribedToo": "a4ufoAB"}'
Not sure where to go now :-/
You can use a JSON path condition with the ## (exists) operator:
select *
from vegiano_dev."subscription-tokens"
where "subscriptionHistory" ## '$[*].userSubscribedToo == "a4ufoAB"'
The #> will work as welll, but because subscriptionHistory is an array, you need to use an array with that operator:
where "subscriptionHistory" #> '[{"userSubscribedToo": "a4ufoAB"}]'
This assumes that subscriptionHistory is defined as jsonb which it should be. If it's not, you need to cast it: "subscriptionHistory"::jsonb

JSONB filter on select via Supabase

I have such a logic (attributes column's type is JSONB - array of objects) that works:
But I want to implement logical OR here if trait_type is equal ... not AND:
JSONB's column structure:
[
{
"value":"Standard Issue Armor 1 (Purple)",
"trait_type":"Clothes"
},
{
"value":"Standard Issue Helmet 1 (Red)",
"trait_type":"Full Helmet"
},
{
"value":"Chrome",
"trait_type":"SmartSkin"
},
{
"value":"Base Drone (Blue)",
"trait_type":"Drone"
},
{
"value":"Thick",
"trait_type":"Eyebrows"
}
]
How that could be done?
Thanks in advance!
I didn't verify the code, so might not work, but I believe at least is in the right direction. You can use the .or() filter to connect multiple filters with logical or operator. For contains(), you can use the cs keyword inside the or filter like this:
const { data, error } = await supabase.from('NTFs')
.select('name, id_in_collection, owner_address')
.eq('collection_id', Number(id))
.contains('attributes', JSON.stringify([{trait_type: 'SmartSkin', value: 'Chrome'}]))
.or(`attributes.cs.${JSON.stringify([{trait_type: 'Drone', value: 'Armed Drone (Blue)'}])}`, `attributes.cs.${JSON.stringify([{trait_type: 'Drone', value: 'Armed Drone (Green)'}])}`)
.order('id_in_collection')
.range(fromIndex, toIndex)

Hasura 2.0, is there a way to use wildcards?

Hello everyone I am having some issues with the way I used to query my data before updating to Hasura 2.0 (I am currently on Beta 1), so Before 2.0 if you sent a null value to a query it would act as a wildcard * , now that I updated to 2.0 all query variables must have non-null values, is there anyway I could get around this?
A small query will serve as an example:
query get_student_organization($authorId: Int, $gradeId: Int, $groupId: Int, $schoolId: Int) {
validation: student_organization(where: {author_id: {_eq: $authorId}, escuela_id: {_eq: $schoolId}, grado_id: {_eq: $gradeId}, grupo_id: {_eq: $groupId}}) {
id
}
}
so if I send it with only
{"authorId": 5455}
I expect all other variables to act as wildcards.
Any help is welcome :)
you can simply send your whole where object from your front-end!
That way you can simply omit the null variables at all. For this, you need to tweak your query a little bit.
query get_student_organization($wh_frontend: student_organization_bool_exp!) {
validation: student_organization(where: $wh_frontedn) {
id
}
}
In the variables section, add your non-null variables only:
{
"where_fe": {
"authorId": 5455
}
}
so this time your haven't sent the schoolId, groupId and gradeId which serves your need for a wild-card.

Average of grouped data in column using Sequelize

I'm trying to find the average of a 'ratings' column for all the data that has the same 'VenueId'. I have it working with raw code but need to adapt it in Sequelize. The working raw code is
SELECT venueId, AVG(rating) AS average FROM reviews GROUP BY VenueId
The code I've tried is
Review.findAll({
order: [[Sequelize.fn('AVG', Sequelize.col('rating'))]]
}).then(function(Venues) {})
I'm getting an error:
Executing (default): SELECT id, review, rating, createdAt, updatedAt,
VenueId FROM Reviews AS Review ORDER BY max(rating); Unhandled
rejection SequelizeDatabaseError: UNKNOWN_CODE_PLEASE_REPORT:
Expression #1 of ORDER BY contains aggregate function and applies to
the result of a non-aggregated query.
Any ideas?
This might need some tweaking as I don't know your models, but I suggest you try the following:
Review.findAll({
attributes: ['venueId', [models.sequelize.fn('AVG', models.sequelize.col('venue_id')), 'venueIdCount']],
group: 'venue_id'
order: [[models.sequelize.fn('AVG', models.sequelize.col('venue_id')), 'DESC']]
}).then(function() {
//Do something
}})
Important to notice: When I use "venueId" I mean the name of the attribute on your model, and when I use "venue_id" I mean the name of the column in your database table. They might be the same or different, so feel free to tweak it.
You must do this
Review.findAll({
attributes: ['venueId', [models.sequelize.fn('AVG',
models.sequelize.col('rating')), 'ratingAvg']],
group: ['venueId'],
order: [[models.sequelize.fn('AVG', models.sequelize.col('rating')), 'DESC']]
}).then(function() {
//Do something
}})
Or this with async/await
async(() => {
return await(Review.findAll({
attributes: ['venueId', [models.sequelize.fn('AVG',
models.sequelize.col('rating')), 'ratingAvg']],
group: ['venueId'],
order: [[models.sequelize.fn('AVG', models.sequelize.col('rating')), 'DESC']]}))
})

Compare two fields in Waterline/Sails.js query

I want to compare two fields in my Waterline query in Sails.js application, e.g.: SELECT * FROM entity E WHERE E.current < E.max.
I've tried the following code, but it's expecting integer value to be passed to it instead of column name:
Entity.find({
where: {
current: {'<': 'max'}
}
});
So, how do I compare two columns?
I have ran some tests and at the same time read the Waterline documentation. There is no indication of anything that could possibly do comparison of two fields/columns via .find() or .where() methods. Reference: http://sailsjs.org/documentation/concepts/models-and-orm/query-language
Instead, I have used .query() method to compare two fields via SQL string such as :
Entity.query("SELECT * FROM `Entity` E WHERE E.current < E.max", function( err, res) {
if(err) {
//exception
} else {
console.log('response',res);
}
});
The other way would be to use one query to get the max before putting it in the criteria.
EntityOne.find({
sort: 'column DESC'
}).limit(1)
.exec(function(err,found){
var max = found[0]
EntityTwo.find({
where: {
current: {'<': found}
}
}).exec((err,found) {
// Do stuff here
});
});
The query method is ultimately going to be faster however