OJD2AWBJJRUXYVF5BBYWSRRIE5A7LKJDL6YQCQZ3APEBIB6GATFAC
HVXAGQL3ODR3M46AQSASGGNFWSLYUNAHDIBN5DS4IGC4FHTT5JMAC
D367PKGCUNOUEO7QBPFSP3L2XOYXTRALYL7RMPY7XFO6UHQNFPCAC
72DUSPYXB64ECTFQWWD7XSY4YJUNRCFZT22AS4BDRIIUZP33CZGAC
63VXWIHIAKGK7J4VTNRUAG2V32N2QUSWFELB6GD34S54FGRWAPCQC
E4HFJ4L4PAGV7R7EXVG2B2CWDGGW7XWU4D37VURZ66HZ3ILHCFUAC
GQ2TJSGOGNH4PKDNN5ZWITLOE6YNAWO6TCBCQV4SN7ZRWEB6IZ5AC
JAAJEH57DRFXCZGAPOQLI4MN7N57OG52E7TQCC4FFJSOPDX4M65QC
NAAQ2HMF7NXGJDRPXATVAGGZWL5MAIQWF4K5S23VFYBPOPZUXJZAC
47JKAGWEDSPFXKMFOVMTEYGUFFS5SEJMNZIZPJJAWJ5U3CH5YGMQC
PEVQ4WY77RA6HMHM2C4HLJ5YKRLHYCAD7MDIWD6POZTJZMMMBVGAC
NF2TA3BN5FXWG6LFHHI3IDBVRPMLVRNUUZBE3NWIBASMSKEQPC4QC
WYTMZJFYVKHR4QH7AV5JUNWXT6NAC5NNQNPZCQSDI6LGI7DVXFYAC
create or replace function get_products(
create or replace function contains_contained_by (anyarray, anyarray) returns boolean as $$
select $1 <@ $2 and $1 @> $2
$$ language sql parallel safe immutable;
create operator <@> (
procedure = contains_contained_by,
leftarg = anyarray,
rightarg = anyarray
);
create or replace function common(
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') then json_agg(distinct variant_id)
when type in ('capsule', 'tea', 'gummy', 'mint', 'chocolate', 'baked') and not array_agg(distinct variant_id) <@> (select array_agg(variant_id) from variant where product_id = poop.product_id) then json_agg(distinct variant_id)
product_id,
type,
poop.product_id,
type,--think about what order bys will make separating by concentration by important. obvious ones are sort by thc / cbd. 2.5mg argyle on top, 10mg argyle on bottom. in all other cases, 2.5mg and 10mg argyle should be one product and not duplicated. price maybe. producer / brand / name definitely not. what wheres will show both? if both are shown, does order matter? before implementing stackoverflow.com/q/28560389 stackoverflow.com/q/10614505 "gaps and islands". more efficient to group by once compared to group by => (row_number or lag + sum) + group by
create or replace function similar_products(
_product_id integer,
_store_id integer = null,
in_stock boolean = null
create or replace function get_products(
_store_ids integer[] = null,
_species species[] = null,
_effects effect[] = null,
_strain_ids integer[] = null,
_types product_type[] = null,
frequency text = 'daily',
in_stock boolean = null,--true in stock only. false oos only. null everything
search text = null,
min_thc2tc decimal = null,
max_thc2tc decimal = null,
--_user_id integer = null, cte vs plpgsql variable?. will replace below parameters once user stuff is done
akt1 akt1 = null,
comt comt = null,
cyp2c9 cyp2c9 = null,
cyp2c19_2 cyp2c19_2 = null,
cyp2c19_3 cyp2c19_3 = null,
cyp2c19_17 cyp2c19_17 = null
select
product_id,
variant_ids,
type,
producer,
brand,
name,
species,
strain,
array_to_json(terpenes),
image,
cbd,
thc,
min_price,
min_portions,
max_portions
from common(
_store_ids => _store_ids,
_species => _species,
_effects => _effects,
_strain_ids => _strain_ids,
_types => _types,
frequency => frequency,
in_stock => in_stock,
search => search,
min_thc2tc => min_thc2tc,
max_thc2tc => max_thc2tc,
akt1 => akt1,
comt => comt,
cyp2c9 => cyp2c9,
cyp2c19_2 => cyp2c19_2,
cyp2c19_3 => cyp2c19_3,
cyp2c19_17 => cyp2c19_17
)
$$ language sql stable;
create or replace function similar_products(
_variant_id integer,
_store_ids integer[] = null,
_species species[] = null,
_effects effect[] = null,
_strain_ids integer[] = null,
_types product_type[] = null,
frequency text = 'daily',
in_stock boolean = null,--true in stock only. false oos only. null everything
search text = null,
min_thc2tc decimal = null,
max_thc2tc decimal = null,
--_user_id integer = null, cte vs plpgsql variable?. will replace below parameters once user stuff is done
akt1 akt1 = null,
comt comt = null,
cyp2c9 cyp2c9 = null,
cyp2c19_2 cyp2c19_2 = null,
cyp2c19_3 cyp2c19_3 = null,
cyp2c19_17 cyp2c19_17 = null
) returns table(
product_id integer,
variant_ids json,
type product_type,
producer text,
brand text,
name text,
species species,
strain text,
terpenes json,
image text,
cbd numrange,
thc numrange,
min_price decimal(5, 2),
min_portions smallint,
max_portions smallint
) as $$--this is different. input should be variant(10mg, 2.5mg). its product_id should be excluded from result set incase another variant is "similar". but also, group by product id. don't show the same different gummy twice for example because two different concentration per pack. this is also a problem with get_products. if both different concentrations are recommended to the user, should be just one. only if filters showing only one of the concentrations at a time is ok. concrete example. if only 2.5mg is safe, product card link => 2.5mg highlight. same with 10. but if both are safe, don't show up as two cards. does group by change the order? how can I group by only if beside each other??
min,
first
from
product
left outer join strain using (strain_id)
left outer join (
select distinct on(product_id)--https://dba.stackexchange.com/a/159899
product_id,
destination
from
product_image
--order by rank
) as product_image using (product_id)
inner join (--aggregate first, then join https://stackoverflow.com/a/27626358 I think this counts as "retrieve all or most"? obviously more filters maybe not, but let's optimize later
select
product_id,
range_merge(cbd) as cbd,
range_merge(thc) as thc,
min(price),
first(quantity)--this is used to convert mg / g to mg / piece for edibles
from
menu_item
inner join variant using (variant_id)
where
store_id = _store_id or _store_id is null and
case
when in_stock then stock > 0
when not in_stock then stock = 0
else true
end
group by
product_id
) as product_agg using (product_id)
where
show = true and
product_id != _product_id--this is the only thing stopping function reuse, and referencing columns not in select in the order by
min_price,
min_portions,
max_portions
from common(
_store_ids => _store_ids,
_species => _species,
_effects => _effects,
_strain_ids => _strain_ids,
_types => _types,
frequency => frequency,
in_stock => in_stock,
search => search,
min_thc2tc => min_thc2tc,
max_thc2tc => max_thc2tc,
akt1 => akt1,
comt => comt,
cyp2c9 => cyp2c9,
cyp2c19_2 => cyp2c19_2,
cyp2c19_3 => cyp2c19_3,
cyp2c19_17 => cyp2c19_17
)
where product_id != (select product_id from p)
levenshtein(terpenes[1], (select terpenes[1] from p)) <= 2 desc nulls last,--temporary until similarity algorithm between two rank ordered lists is found
levenshtein(terpenes[1], (select terpenes[1] from p)) <= 2 desc nulls last,--replace with http://sigaev.ru/git/gitweb.cgi?p=smlar.git;a=blob;hb=HEAD;f=README https://medium.com/@Alibaba_Cloud/keyword-analysis-with-postgresql-algorithms-for-text-analysis-with-the-smlar-plug-in-64ad32475026 using terpene weights 3:2:1 or 2.5:2:1 or bccannabisstores.com
round(@ avg_range(thc) - (select avg_range(thc) from p), -1) asc nulls last--this is wrong thc_mg, but temporary(take into account user pref for flower, recommend at variant level) but maybe doesn't matter since same type? need to fix if type becomes optional though
--nice la
--since thc_mg is last, don't need to round.
@ avg_range(thc) - (select avg_range from p) asc nulls last,--won't work if type becomes optional though
@ avg_range(thc) / ((min_portions + max_portions) / 2) - (select avg_range / first from p) asc nulls last
let s = Number(parameters.store);
if(Number.isInteger(s)) {
qs += `_store_id => $${params.push(s)},`;
if(Array.isArray(parameters.stores) && (parameters.stores = parameters.stores.map(Number)).every(Number.isInteger)) {
qs += `_store_ids => $${params.push(parameters.stores)},`;