id | name | ipAddress ----+----------+------------------------- 1 | testname | {192.168.1.60,192.168.1.65}
我想用ipAddress
搜索LIKE
。我尝试过:
{'$mac_ip_addresses.ip_address$': { [OP.contains]: [searchItem]}},
这也是:
{'$mac_ip_addresses.ip_address$': { [OP.Like] : { [OP.any]: [searchItem]}}},
ipAddress
的数据类型为text[]
。我想用ipAddress
在LIKE
中搜索。
searchItem
包含需要在ipAddress
字段中搜索的IP,因此我想使用LIKE
在数组中搜索。
答案 0 :(得分:1)
我不知道Sequelize,但是我可以从postgres那里回答。
在PostgreSQL中的数组内搜索模式没有短语法。
如果要分别检查每个数组元素的模式,则需要使用unnest
展开数组:
SELECT id, name, ipaddress
FROM testing
WHERE EXISTS (
SELECT 1 FROM unnest(ipaddress) AS ip
WHERE ip LIKE '8.8.8.%'
);
如果经常以这种方式搜索数组,则最好以规范化形式存储数据。
但是,对于基于相等的搜索(请参见@>
和其他运算符here),有一种简短的语法(加上GIN索引支持)。
SELECT id, name, ipaddress
FROM testing
WHERE ipaddress @> ARRAY['8.8.8.8'];
答案 1 :(得分:1)
~~
是内部用于实现SQL LIKE
的运算符。它没有commutator-没有操作符可以左右切换操作符。
这就是您尝试使用ANY
construct和 left 模式的方式所需要的。相关:
不过,您可以create the operator,这很简单:
CREATE OR REPLACE FUNCTION reverse_like (text, text)
RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT $2 LIKE $1';
CREATE OPERATOR <~~ (function = reverse_like, leftarg = text, rightarg = text);
灵感来自Jeff Janes的想法:
然后您的查询可以在运算符的左左侧具有 pattern :
SELECT *
FROM mac_ip_addresses
WHERE '192.168.2%.255' <~~ ANY (ipaddress);
比EXISTS
表达式demonstrated by filiprem简单但 慢 ,。
然后,对于大表,这两个查询都非常慢,因为两个查询都不能使用索引。具有n:1表且每个表包含一个IP的规范化DB设计将允许这样做。它也将占用磁盘空间的几倍。不过,更清洁的实施方式...
虽然仍停留在当前的设计中,但是仍然有一种方法:在数组的文本表示形式上创建三字母组GIN索引,并向查询中另外添加一个冗余的“可精化”谓词。困惑?这是食谱:
首先,三字母组合索引?如果您不熟悉,请阅读以下内容:
从text[]
到text
或array_to_string()
的转换都是不可变的。但是我们需要一个表达式索引。长话短说,使用不可变的包装函数伪造它:
CREATE OR REPLACE FUNCTION f_textarr2text(text[])
RETURNS text LANGUAGE sql IMMUTABLE AS $$SELECT array_to_string($1, ',')$$;
CREATE INDEX iparr_trigram_idx ON iparr
USING gin (f_textarr2text(iparr) gin_trgm_ops);
有关长话的答案(以及为什么这样比较安全):
然后您的查询可以是:
SELECT *
FROM mac_ip_addresses
WHERE NOT ('192.168.9%.255' <~~ ANY (ipaddress))
AND f_textarr2text(ipaddress) LIKE '192.168.9%.255'; -- logically redundant
添加的谓词在逻辑上是多余的,但可以利用trigram索引的功能。
快很多 用于大型桌子。还是更快一点:
SELECT *
FROM mac_ip_addresses
WHERE EXISTS (SELECT FROM unnest(ipaddress) ip WHERE ip LIKE '192.168.9%.255')
AND f_textarr2text(ipaddress) LIKE '192.168.9%.255';
但是那是次要的。
db <>提琴here
我很感兴趣地回答了所问的问题。公众可能会感兴趣。不过,很可能不是您所需的。
我想用
ipAddress
在LIKE
中进行搜索。searchItem
包含需要在ipAddress
字段中搜索的IP,因此我想使用LIKE
在数组中搜索。
那应该读为:
“我想在数组searchItem
中搜索给定的IP地址(ipAddress
)。我的第一个想法是使用LIKE
...”
嗯,LIKE
用于模式匹配。要在数组中查找完整 IP地址,这是错误的工具。 filiprem's second query和数组运算符是一条路。可能足够好。
使用built-in data type cidr
代替text
会更好。而且,附加的ip4r模块的ip4
数据类型会更好。结合了示范的标准数组运算符。
最后,就性能而言,将IPv4地址转换为integer
并与附加的inrarray module一起使用应该是出色的。