RedisSearch Python客户端
项目描述
RediSearch Python客户端
弃用通知
从redis-py 4.0.0开始,此库已弃用。其功能已合并到redis-py中。请从pypy安装它或从存储库安装。
这是一个利用RediSearch Redis模块 API的Python搜索引擎库。
它是RediSearch的“官方”客户端,应被视为其标准客户端实现。
功能
RediSearch是一个开源(RSAL)、高性能的搜索引擎,作为Redis模块实现。它使用自定义数据类型,允许在Redis内部进行快速、稳定且功能丰富的全文搜索。
此客户端是RediSearch API协议的包装器,允许您轻松利用其功能。
RediSearch的功能包括
- 文档中多个字段的全文索引。
- 增量索引而不会损失性能。
- 文档排名(由用户在索引时手动提供)和字段权重。
- 自动完成建议(具有模糊前缀建议)。
- 精确短语搜索。
- 在多种语言中基于词干提取的查询扩展(使用Snowball)。
- 限制搜索到特定文档字段(支持最多8个字段)。
- 数字过滤和范围。
- 自动索引现有的HASH键作为文档。
更多详细信息,请访问http://redisearch.io
示例
创建客户端实例
创建redisearch-py客户端实例时,唯一必需的参数是索引的名称。
from redisearch import Client
client = Client("my-index")
要使用用户名和/或密码连接,将这些选项传递给客户端初始化器。
client = Client("my-index", password="my-password")
使用核心Redis命令
每个Client
实例都包含一个redis-py Client
实例。使用此对象运行核心Redis命令。
import datetime
from redisearch import Client
START_TIME = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M.%S")
client = Client("my-index")
client.redis.set("start-time", START_TIME)
检查RediSearch索引是否存在
要检查RediSearch索引是否存在,请使用FT.INFO
命令,如果索引不存在,则会引发ResponseError
。
from redis import ResponseError
from redisearch import Client
client = Client("my-index")
try:
client.info()
except ResponseError:
# Index does not exist. We need to create it!
定义搜索索引
使用IndexDefinition
的实例来定义搜索索引。您只有在创建索引时才需要这样做。
RediSearch索引通过监视键前缀来跟踪Redis数据库中的Hash。如果一个以搜索索引配置的键前缀开头的Hash被添加、更新或从Redis中删除,RediSearch将在索引中做出相应的更改。您可以通过IndexDefinition
初始化器的prefix
参数来配置搜索索引的键前缀。
注意:一旦创建索引,RediSearch将在这些键的Hash更改时持续索引这些键。
IndexDefinition
还接受一个模式。该模式指定从索引跟踪的Hash中索引哪些字段。字段类型是
- TextField
- TagField
- NumericField
- GeoField
有关这些字段类型含义的更多信息,请参阅RediSearch文档中的FT.CREATE
命令。
在redisearch-py中,模式是Field
实例的迭代器。一旦您有一个IndexDefinition
实例,您可以通过将模式迭代器传递给create_index()
方法来创建实例。
from redis import ResponseError
from redisearch import Client, IndexDefinition, TextField
SCHEMA = (
TextField("title", weight=5.0),
TextField("body")
)
client = Client("my-index")
definition = IndexDefinition(prefix=['blog:'])
try:
client.info()
except ResponseError:
# Index does not exist. We need to create it!
client.create_index(SCHEMA, definition=definition)
索引文档
RediSearch 2.0索引持续跟踪您定义的键前缀的Hash,因此如果您想将文档添加到索引中,您只需创建一个具有这些前缀之一的Hash。
# Indexing a document with RediSearch 2.0.
doc = {
'title': 'RediSearch',
'body': 'Redisearch adds querying, indexing, and full-text search to Redis'
}
client.redis.hset('doc:1', mapping=doc)
RediSearch的旧版本要求您调用add_document()
方法。此方法已弃用,但为了参考,我们在此处包含其用法。
# Indexing a document for RediSearch 1.x
client.add_document(
"doc:2",
title="RediSearch",
body="Redisearch implements a search engine on top of redis",
)
查询
基本查询
使用search()
方法执行基本全文和字段特定搜索。此方法不包含RediSearch FT.SEARCH
命令中可用的许多选项--请参阅本文档后面的“构建复杂查询”部分,了解如何使用这些选项。
res = client.search("evil wizards")
结果对象
结果被包装在包含结果数量和匹配文档列表的Result
对象中。
>>> print(res.total)
2
>>> print(res.docs[0].title)
"Wizard Story 2: Evil Wizards Strike Back"
构建复杂查询
您可以使用Query
对象构建复杂查询
q = Query("evil wizards").verbatim().no_content().with_scores().paging(0, 5)
res = client.search(q)
有关这些选项的解释,请参阅RediSearch文档中的FT.SEARCH
命令。
查询语法
查询的默认行为是在索引中的所有TEXT
字段上执行全文搜索,以匹配查询中所有术语的交集。
因此,本README“基本查询”部分中给出的示例client.search("evil wizards")
将在所有TEXT
字段中搜索“邪恶”和“巫师”的交集。
然而,可能的查询类型还有很多!传递给search()
方法或Query()
初始化器的字符串具有RediSearch中可用的完整查询语法。
例如,对索引中特定 TEXT
字段的全文搜索如下所示
# Full-text search
res = client.search("@title:evil wizards")
查找2020年或2021年出版的书籍如下所示
client.search("@published_year:[2020 2021]")
想了解更多信息,请参阅RediSearch查询语法文档。
聚合查询
该库包含一个程序接口,用于运行RediSearch的聚合查询。
制作聚合查询
要制作聚合查询,请将AggregateRequest
类的实例传递给Client
实例的search()
方法。
例如,查找单一年度出版书籍最多的情况如下所示
from redisearch import Client
from redisearch import reducers
from redisearch.aggregation import AggregateRequest
client = Client('books-idx')
request = AggregateRequest('*').group_by(
'@published_year', reducers.count().alias("num_published")
).group_by(
[], reducers.max("@num_published").alias("max_books_published_per_year")
)
result = client.aggregate(request)
redis-cli等价查询
上面给出的聚合查询相当于在redis-cli中直接输入以下FT.AGGREGATE
命令
FT.AGGREGATE books-idx *
GROUPBY 1 @published_year
REDUCE COUNT 0 AS num_published
GROUPBY 0
REDUCE MAX 1 @num_published AS max_books_published_per_year
聚合结果对象
聚合查询返回一个包含查询返回的行和一个游标的AggregateResult
对象,如果您正在使用游标API。
from redisearch.aggregation import AggregateRequest, Asc
request = AggregateRequest('*').group_by(
['@published_year'], reducers.avg('average_rating').alias('average_rating_for_year')
).sort_by(
Asc('@average_rating_for_year')
).limit(
0, 10
).filter('@published_year > 0')
...
In [53]: resp = c.aggregate(request)
In [54]: resp.rows
Out[54]:
[['published_year', '1914', 'average_rating_for_year', '0'],
['published_year', '2009', 'average_rating_for_year', '1.39166666667'],
['published_year', '2011', 'average_rating_for_year', '2.046'],
['published_year', '2010', 'average_rating_for_year', '3.125'],
['published_year', '2012', 'average_rating_for_year', '3.41'],
['published_year', '1967', 'average_rating_for_year', '3.603'],
['published_year', '1970', 'average_rating_for_year', '3.71875'],
['published_year', '1966', 'average_rating_for_year', '3.72666666667'],
['published_year', '1927', 'average_rating_for_year', '3.77']]
减少器函数
从示例中可以看出,我们使用了reducers
模块中的一个对象。有关在使用分组结果时可以使用的减少器函数的更多示例,请参阅RediSearch文档。
减少器函数包括一个alias()
方法,该方法为减少器结果赋予一个特定的名称。如果您不提供名称,RediSearch将生成一个。
按零、一个或多个字段分组
group_by
语句可以接受一个字段名称作为字符串,也可以接受多个字段名称作为字符串列表。
AggregateRequest('*').group_by('@published_year', reducers.count())
AggregateRequest('*').group_by(
['@published_year', '@average_rating'],
reducers.count())
要对聚合查询的每个结果运行减少器函数,请将空列表传递给group_by()
,这在redis-cli中编写聚合查询时相当于传递选项GROUPBY 0
。
AggregateRequest('*').group_by([], reducers.max("@num_published"))
注意:聚合查询至少需要一个group_by()
方法调用。
排序和限制
使用AggregateRequest
实例,您可以使用sort_by()
方法进行排序,并使用limit()
方法进行限制。
例如,查找每年出版书籍的平均评分,按年度平均评分排序,并仅返回前十个结果
from redisearch import Client
from redisearch.aggregation import AggregateRequest, Asc
c = Client()
request = AggregateRequest('*').group_by(
['@published_year'], reducers.avg('average_rating').alias('average_rating_for_year')
).sort_by(
Asc('@average_rating_for_year')
).limit(0, 10)
c.aggregate(request)
注意:limit()
的第一个选项是零基偏移量,第二个选项是要返回的结果数量。
过滤
使用过滤在减少器函数运行后拒绝聚合查询的结果。例如,计算每年出版书籍的平均评分,并仅返回平均评分高于3的年份
from redisearch.aggregation import AggregateRequest, Asc
req = AggregateRequest('*').group_by(
['@published_year'], reducers.avg('average_rating').alias('average_rating_for_year')
).sort_by(
Asc('@average_rating_for_year')
).filter('@average_rating_for_year > 3')
安装
- 安装RediSearch
- 安装Python客户端
$ pip install redisearch
开发
- 创建一个虚拟环境来管理您的Python依赖项,并确保它已激活。
virtualenv -v venv
- 安装pypoetry以管理您的依赖项。
pip install --user poetry
- 安装依赖项。
poetry install
注意:由于与python 3.10的交互,您可能需要运行以下命令,如果在安装包时收到JSONError。
poetry config experimental.new-installer false
测试
可以使用Docker轻松进行测试。运行以下命令
make -C test/docker test PYTHON_VER=3
(将PYTHON_VER=3
替换为PYTHON_VER=2
以使用Python 2.7进行测试。)
或者,使用以下步骤
首先,运行
PYTHON_VER=3 ./test/test-setup.sh
这将在一个名为venv3
的Python虚拟环境中设置一个Python虚拟环境(如果使用PYTHON_VER=2
,则是在venv2
中)。
之后,以守护进程方式在一个容器中运行RediSearch
docker run -d -p 6379:6379 redislabs/redisearch:2.0.0
最后,调用虚拟环境并运行测试
. ./venv3/bin/activate
REDIS_PORT=6379 python test/test.py
REDIS_PORT=6379 python test/test_builder.py
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。