这可能是一个非常简单的问题,所以提前道歉,但我对数据库的使用非常新.
我想让Postgres在多个连接表中运行全文搜索.想象一下像模型用户,具有相关模型UserProfile和UserInfo.搜索仅适用于用户,但包含来自UserProfile和UserInfo的信息.
我打算在搜索中使用杜松子酒索引.但是,我不清楚我是否需要在User表中使用单独的tsvector列来保存表中的聚合tsvector,并设置触发器以使其保持最新.或者,如果可以创建没有tsvector列的索引,只要任何相关表中的任何相关字段发生更改,它就会保持最新状态.此外,任何关于创建所有这些的命令的语法的提示也将非常受欢迎.
我目前正在运行Rails迁移,我正在添加一个特定于Postgres,tsvector的数据类型.它以Postgres期望的内置文本搜索功能的形式保存搜索信息.
这是我迁移的一行:
t.column "search_vectors", :tsvector
Run Code Online (Sandbox Code Playgroud)
一切似乎都运行正常,搜索也适用.但是,当我打开schema.rb时,这就是我得到的:
Could not dump table "users" because of following StandardError
Unknown type 'tsvector' for column 'search_vectors'
Run Code Online (Sandbox Code Playgroud)
这使我无法在用户表上运行单元测试,并且鉴于schema.rb应该是我的数据库的权威定义,这也让我觉得非常危险.
我注意到有许多Rails插件似乎使用了像我期望的那样存储tsvector的相同方法,例如tsearchable.我真的只是坚持没有测试,没有我的数据库的权威定义?
migration postgresql ruby-on-rails tsvector custom-data-type
我已经被邀请参与一个项目的帮助,并且在几年没有使用它之后我又回到了PostgreSQL.除了缺乏使用之外,我以前从未遇到使用tsvector字段,现在发现自己面临着基于它们的错误.我阅读了关于字段类型及其目的的文档,但是我很难将关于"简单"与"英语"的区别的文档作为to_tsquery()的第一个参数进行挖掘
例
> SELECT to_tsvector('mortgag') @@ to_tsquery('simple', 'mortgage')
?column?
----------
f
(1 row)
> SELECT to_tsvector('mortgag') @@ to_tsquery('english', 'mortgage')
?column?
----------
t
(1 row)
Run Code Online (Sandbox Code Playgroud)
我认为他们都应该回归真实,但显然第一次没有 - 为什么?
我正在尝试清理涉及用户输入的字符串,而不必在可能的情况下手动制作我自己的可能错误的正则表达式,但是,如果这是唯一的方式我也会感激如果有人能指出我正确的方向正则表达式不太可能遗漏任何东西.Rails中有许多方法可以让你输入本机SQL命令,人们如何逃避用户输入?
我问的问题很广泛,但在我的特殊情况下,我正在使用Postgres数据库中的一个专栏,据我所知,Rails本身并不理解tsvector,它包含纯文本搜索信息.Rails能够写入和读取它,就像它是一个字符串一样,但是,与字符串不同,当我在模型中执行vector =之类的事情时,它似乎并没有自动转义它.
例如,当我做model.name ='::',其中name是一个字符串,它工作正常.当我做model.vector ='::'时出错了:
ActiveRecord::StatementInvalid: PGError: ERROR: syntax error in tsvector: "::"
"vectors" = E'::' WHERE "id" = 1
Run Code Online (Sandbox Code Playgroud)
这似乎是由于缺少分号的转义而导致的问题,我可以手动设置vector ='''罚款.
我也有一个好主意,也许我可以称之为:
ActiveRecord::Base.connection.execute "UPDATE medias SET vectors = ? WHERE id = 1", "::"
Run Code Online (Sandbox Code Playgroud)
但是,这种语法不起作用,因为原始SQL命令无法通过使用?来查找转义和输入字符串的方法.标记.
这与我用任何类型的用户输入调用connection.execute同样的问题,因为它归结为清理字符串,但我似乎无法找到任何方法手动调用Rails的SQL字符串清理方法.有人可以提供任何建议吗?
使用 Postgres,我想使用索引执行包含数组列的全文搜索。让我们从一个假设的模式开始:
CREATE TABLE book (title TEXT, tags TEXT[]);
-- tags are lowercase a-z, dashes, and $
Run Code Online (Sandbox Code Playgroud)
我们想要一个在标题和标签中搜索某些文本的查询。许多 SO 答案推荐的具有合理语义的简单查询是:
SELECT *
FROM book
WHERE to_tsvector('simple', array_to_string(tags, ' ')) || to_tsvector('simple', title)
@@ to_tsquery('simple', 'mysearchterm');
Run Code Online (Sandbox Code Playgroud)
这样可行。标签中的破折号和美元符号实际上不再存在,但这对于此应用程序来说是可以的。然而,我们有数百万条记录,需要一个索引:
CREATE INDEX book_fulltext_idx
ON book using GIN
((to_tsvector('simple', array_to_string(tags, ' ')) || to_tsvector('simple', title)));
Run Code Online (Sandbox Code Playgroud)
呃哦!这会失败,因为它array_to_string
不是 IMMUTABLE。有一些答案建议将 array_to_string 包装在不可变函数中:
CREATE FUNCTION my_array_to_string(arr ANYARRAY, sep TEXT)
RETURNS text LANGUAGE SQL IMMUTABLE
AS $$
SELECT array_to_string(arr, sep);
$$;
CREATE INDEX book_fulltext_idx
ON book using GIN …
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法来模拟SELECT * FROM table WHERE attr LIKE '%text%'
在PostgreSQL中使用tsvector之类的东西.
我没有使用字典就创建了一个tsvector属性.现在,像...这样的查询
SELECT title
FROM table
WHERE title_tsv @@ plainto_tsquery('ph:*');
Run Code Online (Sandbox Code Playgroud)
...将返回所有标题,如'Physics','PHP'等.但是,如何创建一个返回所有标题的查询,其中标题以'Zend Fram'开头(应该返回例如'Zend Framework')?
当然,我可以使用类似的东西:
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend')
AND title_tsv @@ to_tsquery('fram:*');
Run Code Online (Sandbox Code Playgroud)
然而,这似乎有点尴尬.
所以,问题是:有没有办法用以下方法制定上面给出的查询:
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend fram:*');
Run Code Online (Sandbox Code Playgroud) 我正在使用PostgeSQL 9.2.2.我的数据库架构是
pg_rocks_post
title | character varying(1024) | not null
body | text | not null
body_title_tsv | tsvector |
body_title_titleupweight_tsv | tsvector |
Run Code Online (Sandbox Code Playgroud)
我创建了body_title_titleupweight_tsv作为类型tsvector.然后,我使用文档中的示例定义了一个触发器,该文档按如下方式对标题进行加权.
pgdj=# CREATE FUNCTION title_upweight_trigger() RETURNS trigger AS $$
begin
new.body_title_titleupweight_tsv :=
setweight(to_tsvector('pg_catalog.english', coalesce(new.title,'')), 'A') ||
setweight(to_tsvector('pg_catalog.english', coalesce(new.body,'')), 'D');
return new;
end
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
我知道触发器有效,因为当我更新pg_rocks_post中的一个条目然后查询它时:我看到它已正确填充了body_title_titleupweight_tsv ts_vector和更新的行.
我的问题是如何将触发器应用于表中的现有行.我只学习postgres,因此我的测试数据库中有几百个条目,想知道如何填充body_title_titleupweight_tsv列.
我认为这样做的一种方法是运行更新并使用类似的东西来编写函数
pgdj=# UPDATE pg_rocks_post SET body_title_titleupweight_tsv =
setweight(to_tsvector( coalesce(title,'')),'A') ||
setweight(to_tsvector(coalesce(body,'')),'D');
Run Code Online (Sandbox Code Playgroud)
而不是在上面的更新语句中再次为触发器重写逻辑.有没有办法通过执行虚拟更新或"触摸"样式操作来触发上面的触发器,该操作会翻转数据库中所有行的触发器.
我试图寻找这种虚拟或"触摸"类型操作的语法或示例,但找不到任何解释如何执行此操作的操作.
tsvector
在列中存储值时,对于没有搜索项的记录,我应该存储空值tsvector
还是NULL
值?
有关系吗?
存储空载体的性能或存储开销是否有任何差异?
换句话说,当基于例如可空title
列的值更新向量时,我是否需要始终将其计算为to_tsvector(coalesce(title,''))
(因为在给定参数时to_tsvector
返回)或者它是否足够?NULL
NULL
to_tsvector(title)
我有一个postgresql视图,它包含3个表的组合:
create view search_view as
select u.first_name, u.last_name, a.notes, a.summary, a.search_index
from user as u, assessor as a, connector as c
where a.connector_id = c.id and c.user_id = u.id;
Run Code Online (Sandbox Code Playgroud)
但是,我需要将3个表中的2个的tsvector字段连接到视图中的单个tsvector字段,该字段提供跨4个字段的全文搜索:2个来自一个表,2个来自另一个.
我已经阅读了文档,声明我可以使用concat运算符来组合两个tsvector字段,但我不确定这在语法上是什么样的,以及是否存在此实现的潜在问题.
我正在寻找将两个tsvector字段从单独的表连接到一个视图中的示例代码,并且还评论这是在postgresql中是一个好的还是坏的做法.
我正在使用Rails在Rails应用程序中创建搜索pg_search gem
.但是,其中一个表有一个Text
数据类型字段,它的内容恰好比平时略大.
现在,当我需要tsvector column
为text
列设置a时,由于文本字段大小与tsvector大小的原因,我面临一些限制.
ERROR: string is too long for tsvector (5068741 bytes, max 1048575 bytes)
Text
在SQL
触发器中创建tsvector列时,是否有任何方法可以确定跳过较大字段的条件以执行以下操作:
伪代码:
execute(<<-TRIGGERSQL)
CREATE OR REPLACE FUNCTION public.essays_before_insert_update_row_tr()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
If (SELECT LEN(body_text) FROM essays) <= 1048575
new.tsv_body_text := to_tsvector('pg_catalog.english', coalesce(new.body_text,''));
RETURN NEW;
End
END;
$function$
TRIGGERSQL
# no candidate create_trigger statement could be found, creating an adapter-specific one
execute("CREATE TRIGGER essays_before_insert_update_row_tr BEFORE INSERT OR UPDATE ON \"essays\" …
Run Code Online (Sandbox Code Playgroud) postgresql ruby-on-rails tsvector rails-postgresql pg-search
tsvector ×10
postgresql ×9
sql ×2
escaping ×1
migration ×1
pg-search ×1
sanitize ×1
sql-update ×1
triggers ×1