# Typesense 数据过滤技巧
本文我们将讨论如何使用多种过滤选项在 Typesense 中过滤数据:
# 基础过滤
Typesense 允许您根据特定字段的值来过滤搜索结果。您可以使用 filter_by
参数指定自定义过滤字符串。
{
"q": "*",
"filter_by": "country:=USA"
// ...
}
请注意,过滤器的基本格式是 字段: <操作符> <值>
。每个过滤字段后面必须有一个 :
。
- ✅ 正确写法:
price:>=100
- ❌ 错误写法:
price>=100
# 可用运算符
运算符 | 描述 | 适用类型 | 示例 |
---|---|---|---|
= | 等于 | string , int32 , int64 , float , bool | country:=USA |
: | 部分等于 | string | country:New |
> | 大于 | int32 , int64 , float | price:>100 |
< | 小于 | int32 , int64 , float | price:<100 |
!= | 不等于 | string , int32 , int64 , float , bool | status:!=inactive |
<= | 小于等于 | int32 , int64 , float | price:<=100 |
>= | 大于等于 | int32 , int64 , float | price:>=100 |
[] | 属于其中之一 | string , int32 , int64 , float , bool | country:[USA, UK, Canada] |
![] | 不属于其中任何一个 | string , int32 , int64 , float , bool | country:![USA, UK, Canada] |
[..] | 范围 | int32 , int64 , float | price:[100..200] |
# 字符串类型的非精确匹配运算符
非精确匹配运算符 (:
) 允许对 string
类型字段进行单词级别的部分匹配。当您需要查找包含特定单词的结果时非常有用:
location:New
该过滤器将匹配所有包含 "New" 的国家/地区名称,例如:
- ✅ 新西兰 (New Zealand)
- ✅ 新喀里多尼亚 (New Caledonia)
- ✅ 巴布亚新几内亚 (Papua New Guinea)
但不会匹配以下位置:
- ❌
纽芬兰 (Newfoundland)
因为 New
在字符串 Newfoundland
中不是一个独立的单词。如果您需要此类匹配,请参阅下面的前缀过滤。
性能提示
非精确匹配运算符 (:
) 不考虑词元位置,因此通常比精确匹配 :=
运算符更快。
# 数组运算符
数组运算符允许您基于特定条件过滤数值字段 (int32
, int64
或 float
):
price:[<20, >100]
将返回价格符合以下条件的商品:
- 低于 20
或
- 高于 100
逗号作为 OR 运算符,允许灵活的条件组合。
# 范围运算符
范围运算符可与多个数组元素一起使用,在范围或值之间创建逻辑 OR 关系:
price:[100..200, 15..50, 800]
这将匹配价格符合以下条件的商品:
- 100 到 200 之间
- 15 到 50 之间
- 恰好为 800
# 空字段过滤
您可能需要筛选特定字段为空或 null 的记录。
由于 Typesense 不允许在 filter_by
中使用完全空的过滤值,您可以使用占位符来实现。
一种方法是使用字母数字占位符(如 ~~
)来查找空字段:
{
"q": "*",
"filter_by": "optional_field:=~~"
}
但要实现这一点,在索引数据时您需要:
- 在集合 schema 的
symbols_to_index
参数中添加您的占位符字符。 - 添加文档时,识别可能为空的字段,并用您选择的占位符(例如
~~
)替换空值或 null 值
// 索引前的预处理示例
const document = {
title: "产品名称",
description: "~~", // 空字段
category: "电子产品"
};
然后,要筛选描述为空的记录:
filter_by = description:=~~
同样地,要筛选描述不为空的记录,可以使用 !
运算符:
filter_by = description:!~~
重要提示:关于占位符符号
默认情况下,Typesense 不会索引符号。
因此要使上述技术生效,您需要在集合 schema 中为特定字段配置 symbols_to_index
参数。
以下是设置带有 symbols_to_index
的 schema 示例:
{
"name": "products",
"fields": [
{"name": "title", "type": "string"},
{"name": "description", "type": "string", "symbols_to_index": ["~"]},
{"name": "category", "type": "string"}
]
}
通过在 symbols_to_index
中包含所需符号,Typesense 将正确索引并允许基于该符号进行过滤。然后您就可以将其用作空字段的占位符:
# 前缀过滤
此功能仅在 Typesense Server v27.0 及以上版本可用
您可以在 string
类型字段过滤器中使用星号 (*
) 表示前缀。这允许您筛选以指定前缀开头的字段:
name:Jo*
该过滤器将返回名字中包含以 Jo
开头的单词的结果,例如:
- Jonathan Jacobs
- John McKinley
- Michael Johansson
当您将前缀与精确匹配运算符 :=
结合使用时,结果将仅包含名称开头与前缀匹配的条目:
name:=Jo*
这将匹配:
- ✅ Jonathan Jacobs
- ✅ John McKinley
但不匹配:
- ❌ Michael Johansson
# 布尔运算
您可以使用逻辑运算符组合多个过滤器。
运算符 | 描述 | 示例 |
---|---|---|
&& | 逻辑与 | country:=USA && city:=New York |
|| | 逻辑或 | country:=USA || country:=Canada |
使用逻辑运算符时,您可以使用括号对过滤器进行分组。
例如,要筛选产自美国或加拿大且位于纽约的产品,可以使用以下过滤器:
(country:=USA || country:=Canada) && city:=New York
这将返回产自美国或加拿大且位于纽约的产品。 使用逻辑运算符时,您可以使用括号对过滤器进行分组。 例如,要筛选产自美国或加拿大且位于纽约的产品,可以使用以下过滤器:
(country:=USA || country:=Canada) && city:=New York
# 运算符优先级
在布尔运算中,AND 运算符 (&&
) 的优先级高于 OR 运算符 (||
)。这意味着除非使用括号指定不同的顺序,否则 AND 运算会先于 OR 运算执行。
例如:
country:=USA || country:=Canada && city:=New York
会被解释为:
country:=USA || (country:=Canada && city:=New York)
要改变运算顺序,可以使用括号:
(country:=USA || country:=Canada) && city:=New York
# 数组类型过滤
任何数组类型都可以用于过滤,匹配其中的任意值。
例如,如果有一个名为 department_prices
的 int32[]
类型字段,且某文档包含 department_prices: [32, 60, 80]
,
那么以下过滤器:
department_prices:<80
将会返回这个文档。
此外,你也可以使用数组运算符:
deparment_prices:[20..80]
# 转义特殊字符
如果要过滤包含特殊字符(如逗号 ,
)的值,可以使用反引号包裹过滤值:
country:=`United States, Minor Outlying Islands`
# 地理位置点过滤
您可以通过两种方式对 geopoint
类型字段进行过滤:在特定半径范围内搜索,或通过指定边界框进行搜索。
例如,要筛选距离特定位置 10 公里半径范围内的结果,可以使用以下过滤条件:
location:(48.90615915923891, 2.3435897727061175, 10 km),
TIP
您可以通过将距离单位改为 mi
来使用相同的过滤器进行英里单位的搜索。
或者,要筛选边界框范围内的结果,可以使用以下过滤条件:
location:(48.8662, 2.3255, 48.8581, 2.3209, 48.8561, 2.3448, 48.8641, 2.3469)
关于如何过滤 geopoint
字段以在特定区域内搜索的更多信息,请参阅我们的地理位置搜索文档。
# 嵌套对象字段过滤
您还可以使用点号(.
)表示法来引用嵌套字段,从而对嵌套对象字段进行过滤。
例如,如果您的集合模式中包含如下所示的 customer
嵌套对象:
{
"customer": {
"name": "John Doe",
"city": "Alpha",
"dob": 964924500
}
}
您可以通过以下方式按客户姓名进行过滤:
customer.name:=John Doe
# 关联集合的过滤
在对关联集合进行过滤时,需要使用 $CollectionName(<filter>)
语法。
例如,如果您有一个 products
集合包含 category
字段,以及一个 categories
集合包含 name
字段,您可以通过以下方式过滤属于 Electronics
类别的产品:
$categories(name:=Electronics)
在关联集合内部,您可以使用任何直接适用于该集合的过滤字符串,包括 &&
、||
和 !
布尔运算符。例如,要过滤同时属于 Electronics
类别和 Mobile
类别,但不属于 Disposable
类别且价格低于 $100 的产品,可以使用以下过滤器:
$categories(name:=Electronics && name:=Mobile && name:!=Disposable) && price:<100
关联字段的过滤支持任意层级的嵌套。如需详细说明和示例,请参阅我们的嵌套关联文档。
WARNING
在过滤器中使用的关联关系必须事先在 schema 中配置好。
更多详情请参见JOINs。