我想在 XML 文档中进行全文搜索。
但是,我无法匹配属性值(如果我提供完整的属性值,包括下例中的:
和/
字符,我会收到语法错误)。另外,我不知道如何为解析器指定我自己的定界符。
下面是SSCCE:
我希望能够选择属性值的最后一个组成部分:attributevalue
并让解析器将:
and识别/
为定界符,因此 yield boo1
, boo2
,some
和attributevalue
作为词位。
DROP TABLE IF EXISTS xmldocument;
CREATE TABLE IF NOT EXISTS xmldocument (
i SERIAL NOT NULL,
content XML NOT NULL
);
ALTER TABLE xmldocument ADD PRIMARY KEY (i);
INSERT INTO xmldocument (content) VALUES
('<a>foo</a>')
,('<a boo=''boo1:boo2:boo3/boo4/some/attributevalue''>foo</a>')
;
-- matches both records as expected
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'foo';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'attributevalue';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'boo2';
-- no match
SELECT * FROM xmldocument WHERE to_tsvector(CAST (content AS VARCHAR))@@'boo4';
至于为什么我不只是使用ILIKE %
等。原因是我需要通过使用 GIN 索引进行优化,我认为在简单的 VARCHAR 值上构建索引是不可能或有意义的。
*接受答案后更新*
根据接受的答案,以下查询均按预期工作:
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('foo');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('attributevalue');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('boo2');
SELECT * FROM fts.xmldocument WHERE
to_tsvector(regexp_replace(content::text,'[<>/]',' ','g')) @@ to_tsquery('boo4');
如果您不想编写自己的解析器,快速而肮脏的解决方案是用一些其他标点符号替换
<
and>
,这样现有的解析器就不会决定将它们作为 html 标记丢弃。如果您使用该
pg_trgm
扩展,您可以在 VARCHAR 值上构建一个 gin 索引,这将优化 ILIKE 查询。它的有效性取决于索引文档的大小和查询的大小。我建议您尝试一下,看看它对您有何帮助。pg_trgm 的 1.2 版(将包含在 PostgreSQL 9.6 中,但如果您愿意编译一些代码,则很容易向后移植到 9.4 和 9.5)对于大型查询将更加有效。