# 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, int64float):

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:=~~"
}

但要实现这一点,在索引数据时您需要:

  1. 在集合 schema 的 symbols_to_index 参数中添加您的占位符字符。
  2. 添加文档时,识别可能为空的字段,并用您选择的占位符(例如 ~~)替换空值或 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_pricesint32[] 类型字段,且某文档包含 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