带有部分句子匹配的 Django 文本搜索更新到 django3
Posted
技术标签:
【中文标题】带有部分句子匹配的 Django 文本搜索更新到 django3【英文标题】:Django text search with partial sentence match update to django3 【发布时间】:2021-05-03 04:44:18 【问题描述】:我正在尝试在 Django postgres 中应用部分搜索,与此处描述的完全相同 django-text-search-with-partial-sentence-match 我发现有一个很好的解决方案
from psycopg2.extensions import adapt
from django.contrib.postgres.search import SearchQuery
class PrefixedPhraseQuery(SearchQuery):
"""
Alter the tsquery executed by SearchQuery
"""
def as_sql(self, compiler, connection):
# Or <-> available in Postgres 9.6
value = adapt('%s:*' % ' & '.join(self.value.split()))
if self.config:
config_sql, config_params = compiler.compile(self.config)
template = 'to_tsquery(::regconfig, )'\
.format(config_sql, value)
params = config_params
else:
template = 'to_tsquery()'\
.format(value)
params = []
if self.invert:
template = '!!()'.format(template)
return template, params
它适用于 python 3.6,但不适用于 3.9。 不同的是,比 3.6 SearchQuery 继承自 Value:
class SearchQuery(SearchQueryCombinable, Value):
output_field = SearchQueryField()
SEARCH_TYPES =
'plain': 'plainto_tsquery',
'phrase': 'phraseto_tsquery',
'raw': 'to_tsquery',
def __init__(self, value, output_field=None, *, config=None, invert=False, search_type='plain'):
self.config = config
self.invert = invert
if search_type not in self.SEARCH_TYPES:
raise ValueError("Unknown search_type argument '%s'." % search_type)
self.search_type = search_type
super().__init__(value, output_field=output_field)
并且在 python 3.9 SearchQuery 中继承自 Func:
class SearchQuery(SearchQueryCombinable, Func):
output_field = SearchQueryField()
SEARCH_TYPES =
'plain': 'plainto_tsquery',
'phrase': 'phraseto_tsquery',
'raw': 'to_tsquery',
'websearch': 'websearch_to_tsquery',
def __init__(self, value, output_field=None, *, config=None, invert=False, search_type='plain'):
self.function = self.SEARCH_TYPES.get(search_type)
if self.function is None:
raise ValueError("Unknown search_type argument '%s'." % search_type)
if not hasattr(value, 'resolve_expression'):
value = Value(value)
expressions = (value,)
self.config = SearchConfig.from_parameter(config)
if self.config is not None:
expressions = (self.config,) + expressions
self.invert = invert
super().__init__(*expressions, output_field=output_field)
Func 与 Value 不同,没有self.value
class Func(SQLiteNumericMixin, Expression):
"""An SQL function call."""
function = None
template = '%(function)s(%(expressions)s)'
arg_joiner = ', '
arity = None # The number of arguments the function accepts.
def __init__(self, *expressions, output_field=None, **extra):
if self.arity is not None and len(expressions) != self.arity:
raise TypeError(
"'%s' takes exactly %s %s (%s given)" % (
self.__class__.__name__,
self.arity,
"argument" if self.arity == 1 else "arguments",
len(expressions),
)
)
super().__init__(output_field=output_field)
self.source_expressions = self._parse_expressions(*expressions)
self.extra = extra
价值看起来像这样
class Value(Expression):
"""Represent a wrapped value as a node within an expression."""
def __init__(self, value, output_field=None):
"""
Arguments:
* value: the value this expression represents. The value will be
added into the sql parameter list and properly quoted.
* output_field: an instance of the model field type that this
expression will return, such as IntegerField() or CharField().
"""
super().__init__(output_field=output_field)
self.value = value
谁能帮我将代码示例调整为 python 3.9 或推荐任何类似搜索的解决方案?
【问题讨论】:
【参考方案1】:所以我们很清楚,您的问题不是 Python 版本,而是 Django 版本。
你要找的应该是self.source_expressions[0]
。
但是,如果我今天重写此代码,我会先查看 raw
search type (example),然后使用邻近运算符 <->
(example) 传递我自己的查询。
【讨论】:
感谢您重新搜索原始搜索类型。当我尝试用self.source_expressions[0]
替换self.value
时,我收到错误value = adapt("%s:*" % " | ".join(self.source_expressions[0].split())) AttributeError: 'SearchConfig' object has no attribute 'split'
。我试过str(self.source_expressions[0])
,但后来我得到return self.cursor.execute(sql, params) django.db.utils.ProgrammingError: syntax error in tsquery: "<django.contrib.postgres.search.SearchConfig | object | at | 0x7f1c461bc7f0>:*"
抱歉格式化,但comment-formatting的一些规则似乎没有效果
您是否尝试将raw
查询与<->
运算符一起使用?
是的。它确实有效。谢谢。无论如何我对以前的代码很好奇,所以对我有用的是self.source_expressions[1]
以上是关于带有部分句子匹配的 Django 文本搜索更新到 django3的主要内容,如果未能解决你的问题,请参考以下文章