如何使用动态正则表达式匹配 Postgres 中的值
Posted
技术标签:
【中文标题】如何使用动态正则表达式匹配 Postgres 中的值【英文标题】:How to use dynamic regex to match value in Postgres 【发布时间】:2021-08-31 15:52:35 【问题描述】:总结:我有两个表我想从中获取信息:family_values (family_name, item_regex)
和 product_ids (product_id)
以便能够在第三个中更新属性 family_name
。
这里的计划是从小的family_values
表中获取一个json 数组,并使用列值item_regex
对product_id
中的每一行进行测试匹配product_ids
。
更多详细信息:将静态数据从 CSV 导入到 orders
的表中。但是,在评估商品成本和市场价值时,我需要不断地根据 product_id 上的前缀正则表达式(来自 family_values 的 item_regex)匹配来确定族。
在客户端上是这样的:
const families =
FOOBAR: 'Big Ogre',
FOOBA: 'Wood Elf',
FOO: 'Valkyrie'
;
// And to find family, and subsequently COGs and Market Value:
const findFamily = product_id => Object.keys(families).find(f => new RegExp('^' + f).test(product_id));
这对客户来说是一个巨大的打击,所以我在 PG 中创建了一个family_values
表来包含一个代表:family_name、item_regex、cogs、market_value。
然后,product_ids 有一个仅包含应用程序关心的产品的列表(数以百万计)。这实际上与“on before”插入触发器一起使用,以忽略任何不在 product_ids 视图中的 CSV 条目。所以,我想在那之后 product_ids 视图可以被排除在等式之外,因为orders
,在插入只读数据之后,有自己匹配的 product_id。它没有family_name
,所以我仍然有确定客户端的问题。
伪代码:使用family_values 正则表达式匹配orders.product_id 中的family_name 更新订单的family 列 OR 使用新的 family 列更新 product_ids 表,并将其与现有的 on insert 触发器一起使用(现在用于左填充零和规范化数据)。现在我认为这可能只是建议的更新,但对于 PG 中的正则表达式并不是很好。我是PG新手。
问题:但是,我在执行我认为类似于 JS 数组查找操作的操作时遇到了问题。 family_values
已在 item_regex
上进行排序,以便最严格的匹配位于顶部,因此首先找到。
例如,通过排序我们有:
family_values_array = [
"family_name": "Big Ogre", "item_regex": "FOOBAR",
"family_name": "Wood Elf", "item_regex": "FOOBA",
"family_name": "Valkyrie", "item_regex": "FOO"]
因此,product_id
与 ^FOOBA
的比较将产生家庭“木精灵”。
解决方案: 我最终使用的解决方案是简单地使用 concat 写出前面锚定的正则表达式。最后就这么简单。我缺少的关键是:
select * into family_value_row from iol.family_values
where lvl3_id = product_row.lvl3_id and product_row.product_id
like concat(item_regex, '%') limit 1;
整个函数:
create or replace function iol.populate_families () returns void as $$
declare
product_row record;
family_value_row record;
begin
for product_row in
select product_id, lvl3_id from iol.products
loop
-- family_name is what we want after finding the BEST match fr a product_id against item_regex
select * into family_value_row from iol.family_values
where lvl3_id = product_row.lvl3_id and product_row.product_id like concat(item_regex, '%') limit 1;
-- update family_name and value columns
update iol.products set
family_name = family_value_row.family_name,
cog_cents = family_value_row.cog_cents,
market_value_cents = family_value_row.market_value_cents
where product_id = product_row.product_id;
end loop;
end;
$$
LANGUAGE plpgsql;
【问题讨论】:
根据您的描述,我想说您既不需要循环也不需要 PL/pgSQL。很可能这可以使用将三个表放在一起的单个 UPDATE 语句轻松完成。但如果没有更多细节,这真的很难说。 我会添加更多细节。谢谢。 【参考方案1】:使用上面更新的 concat:
select * into family_value_row from iol.family_values
where lvl3_id = product_row.lvl3_id and product_row.product_id
like concat(item_regex, '%') limit 1;
【讨论】:
以上是关于如何使用动态正则表达式匹配 Postgres 中的值的主要内容,如果未能解决你的问题,请参考以下文章