How can i query with to_tsquery for partial words match
For example
records
'hello old world'
'hello world'
'hi welcome'
'hi'
Here i wanted to return all records which includes words 'hello' or 'welcome'
SELECT * FROM accounts_order
WHERE name_tsvector ## to_tsquery('english','hello | welcome');
This returns properly.
Here i tried to implement using django 'objects.extra' query
queryset = Order.objects.extra(where=['name_tsvector ## to_tsquery(%s|%s)'], params=['hello','welcome'])
This query is nor working,got an exception
operator is not unique: unknown | unknown
LINE 1: ...nts_order" WHERE name_tsvector ## to_tsquery(E'olmin'|E'20')
^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
How can i pass this params part as a list?
It appears that you want the | within the string, ie a boolean OR in the tsquery:
regress=> select to_tsquery('english', 'olmin|20');
to_tsquery
----------------
'olmin' | '20'
(1 row)
Django is expanding %s to E'string', so you can't write %s|%s; as you've seen that expands to E'string1'|E'string2' which is interpreted as a boolean OR on the two strings. You must either:
Concatenate the two strings and | in Django with (eg) params=['hello'+'|'+'welcome'] and a single (%s) argument; or
Get Pg to concatenate the two strings with a literal |, eg (%s||'|'||%s)
I'd recommend the first option; it requires you to change the parameters you pass from Python but it produces vastly simpler SQL.
The original is invalid, it's trying to perform a boolean OR on two string literals:
regress=> select to_tsquery('english', 'olmin'|'20');
ERROR: operator is not unique: unknown | unknown
LINE 1: select to_tsquery('english', 'olmin'|'20');
^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
Related
trying found out relation name in public schema that contain string "main" and "parted".
So far I have tried.
\dt public.(*main* | *parted*)
-- ERROR: invalid regular expression: parentheses () not balanced
I also tried the following queries:
SELECT
regexp_match('parted1 new main', '(main|parted\S+)');
SELECT
regexp_matches('main new parted1', '(main|parted\S+)');
SELECT
regexp_substr ('main new parted1', '(main|parted\S+)');
SELECT
regexp_substr ('main new parted1', '(main|parted\S+)');
I expect a pattern that will match substring that have pattern "main" or "parted\S+".
In psql manual:
All regular expression special characters work as specified in Section
9.7.3, except for . which is taken as a separator as mentioned above, * which is translated to the regular-expression notation .*, ? which is translated to ., and $ which is matched literally.
From the quote so it's doable?
I tried full text search by postgresql with this code
SELECT * FROM test_table WHERE MATCH (discription) AGAINST ('remote controller');
name of column is "discription"
keyword is "remote controller"
error message is here
ERROR: syntax error at or near "AGAINST"
1: ...LECT * FROM test_table WHERE MATCH (discription) AGAINST ('...
I can not figure out what's wrong??
As Gordon Linoff said, you are using MySQL syntax in Postrgres. The alternative query for Pstgreses is the following:
SELECT *
FROM test_table
WHERE to_tsvector(discription) ## to_tsquery('remote controller');
In a nutshell... the ts_vector data type is provided for storing preprocessed documents (is a sorted list of distinct lexemes, which are words that have been normalized to merge different variants of the same word). When the tsquery is used to represent processed queries.
more information you can find in the following links:
https://www.postgresql.org/docs/12/textsearch-tables.html#TEXTSEARCH-TABLES-SEARCH
https://www.postgresql.org/docs/12/textsearch.html
Note: to improve the search performance you can use also index on this:
https://www.postgresql.org/docs/12/textsearch-tables.html#TEXTSEARCH-TABLES-INDEX
This query will work:
SELECT * FROM test_table WHERE
difference(discription, 'remote controller') > 2;
The Soundex system is a method of matching similar-sounding names by converting them to the same code.
The soundex function converts a string to its Soundex code. The difference function converts two strings to their Soundex codes and then reports the number of matching code positions. Since Soundex codes have four characters, the result ranges from zero to four, with zero being no match and four being an exact match.
NOTE : the difference function gives the difference between the soundex code of two string.
According to postgresql manual != means the same as <>. In reality, it doesn't seems to be the case:
psql=> select 1 where 1!=-1;
ERROR: operator does not exist: integer !=- integer
LINE 1: select 1 where 1!=-1;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
psql=> select 1 where 1<>-1;
?column?
----------
1
(1 row)
Is this a bug or this is an expected behavior that wasn't covered by the manual?
You need to write a space so that postgres knows, that it's a != operator and not !=-:
select 1 != -1;
Or you can put it in parentheses:
select 1!=(-1);
The SQL standard operator is <>, so it is a good habit to stick with it.
The reason for the behavior difference is explained in the documentation:
There are a few restrictions on your choice of [operator] name:
A multicharacter operator name cannot end in + or -, unless the name also contains at least one of these characters:
~ ! # # % ^ & | ` ?
For example, #- is an allowed operator name, but *- is not. This restriction allows PostgreSQL to parse SQL-compliant commands without requiring spaces between tokens.
Now since <> does not contain any of these characters, PostgreSQL knows that <>- cannot be an operator name, and there is no ambiguity in parsing.
Case:
To accept person_name satisfying following criteria:
Allows any alphabetic symbols
Space
Dash
Apostrophe
Accent grave
Some pre-calculation has been performed to store the name in the string "PERSON_NAME"
LOGIC: SUBSTR(REGEXP_REPLACE(PERSON_NAME,'[^A-Za-z .`''-]+',''),0,50)
SELECT SUBSTR(REGEXP_REPLACE('cafè','[^A-Z|a-z| |.|`|''|-]+'),0,50)
FROM dual;
Passing almost all cases except in case of accented characters:
For example:
Expected result: cafè [i.e symbol above e ` should not be filtered out]
Actual Result: caf
You can use :
select SUBSTR(REGEXP_REPLACE('cafè-` t *'' {','[[:digit:]]') ,0,50) as "String"
from dual;
String
--------------
cafè-` t *' {
since there's no information about numeric expressions in your restriction list.
I tried to run the following query:
select * from table where regexp_like('^{{', text_field)
And got the following error:
too big number for repeat range
Thinking perhaps regexp_like is confusing { for the repeat count operator, I also tried the following variations:
select * from table where regexp_like('^\{\{', text_field)
select * from table where regexp_like('^[{][{]', text_field)
select * from table where regexp_like('^[[:punct:]]{2}', text_field)
None of which worked. For now, text_field like '{{' suffices, but I may want to include a more flexible version of this that would require regular expressions. What's wrong with my approach here? And what does this error message mean?
You are using the prestodb regex_like function in the wrong way:
regexp_like(string, pattern)
Evaluates the regular expression pattern and determines if it is
contained within string. This function is similar to the LIKE
operator, expect that the pattern only needs to be contained within
string, rather than needing to match all of string. In other words,
this performs a contains operation rather than a match operation. You
can match the entire string by anchoring the pattern using ^ and $:
SELECT regexp_like('1a 2b 14m', '\d+b'); -- true