基本操作符
Zilliz Cloud 提供了丰富的基本操作符,可帮助您高效过滤和查询数据。您可以使用这些操作符,根据标量字段、数值计算、逻辑条件等细化搜索条件。掌握这些操作符的用法,是构建精确查询并提升搜索效率的关键。
过滤表达式左侧的值既可以是 Collection 字段名称(例如下文示例中的 status、color 等),也可以是指定元素索引处的 StructArray 子字段名称,例如 filter = 'struct[0][subfield] > 10'。
有关 StructArray 字段中标量过滤的详细信息,请参阅 StructArray 操作符。
比较操作符
比较操作符用于根据相等、不等或大小关系过滤数据,适用于数值字段和文本字段。
支持的比较操作符
-
==(等于) -
!=(不等于) -
>(大于) -
<(小于) -
>=(大于或等于) -
<=(小于或等于)
示例 1:使用等于(==)操作符过滤
假设有一个名为 status 的字段,您需要查找 status 为 "active" 的所有实体。可以使用等于操作符 ==:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'status == "active"'
String filter = "status == \"active\"";
filter := "status == \"active\""
let filter = "status == \"active\"";
std::string filter = "status == \"active\"";
const filter = 'status == "active"';
filter='status == "active"'
示例 2:使用不等于(!=)操作符过滤
要查找 status 不为 "inactive" 的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'status != "inactive"'
String filter = "status != \"inactive\"";
filter := "status != \"inactive\""
let filter = "status != \"inactive\"";
std::string filter = "status != \"inactive\"";
const filter = 'status != "inactive"';
filter='status != "inactive"'
示例 3:使用大于(>)操作符过滤
要查找 age 大于 30 的所有实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'age > 30'
String filter = "age > 30";
filter := "age > 30"
let filter = "age > 30";
std::string filter = "age > 30";
const filter = 'age > 30';
filter='age > 30'
示例 4:使用小于(<)操作符过滤
要查找 price 小于 100 的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'price < 100'
String filter = "price < 100";
filter := "price < 100"
let filter = "price < 100";
std::string filter = "price < 100";
const filter = 'price < 100';
filter='price < 100'
示例 5:使用大于或等于(>=)操作符过滤
要查找 rating 大于或等于 4 的所有实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'rating >= 4'
String filter = "rating >= 4";
filter := "rating >= 4"
let filter = "rating >= 4";
std::string filter = "rating >= 4";
const filter = 'rating >= 4';
filter='rating >= 4'
示例 6:使用小于或等于(<=)操作符过滤
要查找 discount 小于或等于 10% 的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'discount <= 10'
String filter = "discount <= 10";
filter := "discount <= 10"
let filter = "discount <= 10";
std::string filter = "discount <= 10";
const filter = 'discount <= 10';
filter='discount <= 10'
范围操作符
范围操作符用于根据一组特定值过滤数据。Zilliz Cloud 支持使用 IN 检查值是否属于指定集合。
要查找 color 为 "red"、"green" 或 "blue" 的所有实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'color in ["red", "green", "blue"]'
String filter = "color in [\"red\", \"green\", \"blue\"]";
filter := "color in [\"red\", \"green\", \"blue\"]"
let filter = "color in [\"red\", \"green\", \"blue\"]";
std::string filter = "color in [\"red\", \"green\", \"blue\"]";
const filter = 'color in ["red", "green", "blue"]';
filter='color in ["red", "green", "blue"]'
需要检查某个值是否属于值列表时,这种方法非常有用。
模式匹配操作符
模式匹配操作符用于根据通配符模式或正则表达式过滤字符串值。
-
LIKE:用于匹配字符串值中的简单通配符模式。例如,name LIKE "Prod%"可以匹配以Prod开头的值。 -
=~:使用 RE2 正则表达式匹配字符串值。例如,code =~ "E[0-9]{4}"可以匹配包含E1001等错误代码的值。 -
!~:排除与 RE2 正则表达式匹配的字符串值,等同于NOT (field =~ "pattern")。
要查找 name 以 Prod 开头的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'name LIKE "Prod%"'
String filter = "name LIKE \"Prod%\"";
filter := "name LIKE \"Prod%\""
let filter = "name LIKE \"Prod%\"";
std::string filter = "name LIKE \"Prod%\"";
const filter = 'name LIKE "Prod%"';
filter='name LIKE "Prod%"'
要查找 code 中包含 E1001 等错误代码的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'code =~ "E[0-9]{4}"'
String filter = "code =~ \"E[0-9]{4}\"";
filter := "code =~ \"E[0-9]{4}\""
let filter = "code =~ \"E[0-9]{4}\"";
std::string filter = "code =~ \"E[0-9]{4}\"";
const filter = 'code =~ "E[0-9]{4}"';
filter='code =~ "E[0-9]{4}"'
要排除 message 以 DEBUG 开头的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'message !~ "^DEBUG"'
String filter = "message !~ \"^DEBUG\"";
filter := "message !~ \"^DEBUG\""
let filter = "message !~ \"^DEBUG\"";
std::string filter = "message !~ \"^DEBUG\"";
const filter = 'message !~ "^DEBUG"';
filter='message !~ "^DEBUG"'
有关如何选择 LIKE 或正则表达式,以及支持的字段类型、正则表达式语法、转义规则和性能等详细信息,请参阅模式匹配。Zilliz Cloud 还支持在 VARCHAR 字段或 JSON 字符串路径上构建 NGRAM 索引,以加速符合条件的模式匹配过滤。有关详细信息,请参阅 NGRAM。
算术操作符
算术操作符用于根据数值字段的计算结果构建过滤条件。
支持的算术操作符
-
+(加法) -
-(减法) -
*(乘法) -
/(除法) -
%(取模) -
**(幂运算)
示例 1:使用取模(%)操作符
要查找 id 为偶数(即能被 2 整除)的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'id % 2 == 0'
String filter = "id % 2 == 0";
filter := "id % 2 == 0"
let filter = "id % 2 == 0";
std::string filter = "id % 2 == 0";
const filter = 'id % 2 == 0';
filter='id % 2 == 0'
示例 2:使用幂运算(**)操作符
要查找 price 的平方大于 1000 的实体:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'price > 1000'
String filter = "price ** 2 > 1000";
filter := "price ** 2 > 1000"
let filter = "price ** 2 > 1000";
std::string filter = "price ** 2 > 1000";
const filter = 'price ** 2 > 1000';
filter='price ** 2 > 1000'
按位操作符
当整数值用于编码权限、功能开关或状态位等多个标志时,按位操作符非常有用。您可以在过滤表达式中使用这些操作符,检查、组合或比较整数值中的各个位。
对于标量字段,按位操作符适用于 INT8、INT16、INT32 和 INT64 等整数字段类型。
支持的按位操作符
| 操作符 | 名称 | 典型用途 |
|---|---|---|
& | 按位与 | 检查特定位是否已设置。 |
| | 按位或 | 在比较前组合多个位。 |
^ | 按位异或 | 比较两个值之间不同的位。 |
示例:按权限位过滤
假设有一个名为 permissions 的整数字段,其中每一位分别代表一个权限标志:
| 权限标志 | 位值 |
|---|---|
READ | 1 |
WRITE | 2 |
SHARE | 4 |
ADMIN | 8 |
例如,permissions = 5 表示 READ 和 SHARE 位已设置,因为 5 = 1 + 4。
要查找已设置 SHARE 位的实体,请使用按位与(&):
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = "(permissions & 4) == 4"
String filter = "(permissions & 4) == 4";
filter := "(permissions & 4) == 4"
let filter = "(permissions & 4) == 4";
std::string filter = "(permissions & 4) == 4";
const filter = '(permissions & 4) == 4';
filter='(permissions & 4) == 4'
要查找设置 WRITE 位后得到 READ + WRITE + SHARE 权限组合的实体,请使用按位或(|):
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = "(permissions | 2) == 7"
String filter = "(permissions | 2) == 7";
filter := "(permissions | 2) == 7"
let filter = "(permissions | 2) == 7";
std::string filter = "(permissions | 2) == 7";
const filter = '(permissions | 2) == 7';
filter='(permissions | 2) == 7'
要查找权限位与 READ + WRITE + SHARE 仅相差 WRITE 位的实体,请使用按位异或(^):
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = "(permissions ^ 7) == 2"
String filter = "(permissions ^ 7) == 2";
filter := "(permissions ^ 7) == 2"
let filter = "(permissions ^ 7) == 2";
std::string filter = "(permissions ^ 7) == 2";
const filter = '(permissions ^ 7) == 2';
filter='(permissions ^ 7) == 2'
注意:在比较结果前,始终需要用括号包裹按位运算,例如 (permissions & 4) == 4。
逻辑操作符
逻辑操作符用于将多个条件组合成更复杂的过滤表达式,包括 AND、OR 和 NOT。
支持的逻辑操作符
-
AND:组合多个必须全部为真的条件。 -
OR:组合多个条件,其中至少一个条件必须为真。 -
NOT:对条件取反。
示例 1:使用 AND 组合条件
要查找 price 大于 100 且 stock 大于 50 的所有产品:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'price > 100 AND stock > 50'
String filter = "price > 100 AND stock > 50";
filter := "price > 100 AND stock > 50"
let filter = "price > 100 AND stock > 50";
std::string filter = "price > 100 AND stock > 50";
const filter = 'price > 100 AND stock > 50';
filter='price > 100 AND stock > 50'
示例 2:使用 OR 组合条件
要查找 color 为 "red" 或 "blue" 的所有产品:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'color == "red" OR color == "blue"'
String filter = "color == \"red\" OR color == \"blue\"";
filter := "color == \"red\" OR color == \"blue\""
let filter = "color == \"red\" OR color == \"blue\"";
std::string filter = "color == \"red\" OR color == \"blue\"";
const filter = 'color == "red" OR color == "blue"';
filter='color == "red" OR color == "blue"'
示例 3:使用 NOT 排除条件
要查找 color 不为 "green" 的所有产品:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'NOT (color == "green")'
String filter = "NOT color == \"green\"";
filter := "NOT color == \"green\""
let filter = "NOT color == \"green\"";
std::string filter = "NOT color == \"green\"";
const filter = 'NOT color == "green"';
filter='NOT color == "green"'
IS NULL 和 IS NOT NULL 操作符
使用 IS NULL 和 IS NOT NULL 可以查找字段值缺失或已有值的实体。例如,你可以查找尚未设置分类的商品,或已生成向量、可以参与搜索的实体。这两个操作符都适用于受支持的标量字段和向量字段,含义相同:
| 操作符 | 匹配的实体 |
|---|---|
<field> IS NULL | 指定字段的值为 NULL 的实体 |
<field> IS NOT NULL | 指定字段的值为非 NULL 的实体 |
支持的标量字段包括布尔、数值、VARCHAR、JSON 和 ARRAY 字段。这两个操作符不支持 TEXT 字段。
从 Milvus 3.0.3 开始,这两个操作符还支持普通向量字段:FLOAT_VECTOR、BINARY_VECTOR、FLOAT16_VECTOR、BFLOAT16_VECTOR、SPARSE_FLOAT_VECTOR 和 INT8_VECTOR。
操作符不区分大小写:IS NULL 与 is null 等价,IS NOT NULL 与 is not null 等价。
示例:查找字段值缺失或已有值的实体
假设集合 products 已建立索引并加载。集合包含名为 id 的 INT64 主键字段、允许 NULL 值的 VARCHAR 字段 category,以及允许 NULL 值的三维 FLOAT_VECTOR 字段 embedding。集合中已有以下实体:
id | category | embedding |
|---|---|---|
1 | "book" | [0.1, 0.2, 0.3] |
2 | NULL | [0.4, 0.5, 0.6] |
3 | "book" | NULL |
此处省略集合创建和数据插入步骤。有关这些步骤,请参阅可空字段。
要查找尚未生成向量的实体,请使用 embedding IS NULL 进行查询。请根据你的服务配置调整连接设置。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT")
results = client.query(
collection_name="products",
filter="category IS NULL",
output_fields=["id"],
limit=10,
)
print(sorted(entity["id"] for entity in results))
# Expected: [2]
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
import java.util.Collections;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.build());
QueryReq queryReq = QueryReq.builder()
.collectionName("products")
.filter("category IS NULL")
.outputFields(Collections.singletonList("id"))
.limit(10)
.build();
QueryResp queryResp = client.query(queryReq);
System.out.println(queryResp.getQueryResults());
import (
"context"
"fmt"
"log"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
log.Fatal("failed to connect to milvus server: ", err.Error())
}
defer cli.Close(ctx)
rs, err := cli.Query(ctx, milvusclient.NewQueryOption("products").
WithFilter("category IS NULL").
WithOutputFields("id").
WithLimit(10))
if err != nil {
log.Fatal("failed to query: ", err.Error())
}
ids := rs.GetColumn("id")
var result []int64
for i := 0; i < ids.Len(); i++ {
v, _ := ids.GetAsInt64(i)
result = append(result, v)
}
fmt.Println(result)
// Expected: [2]
use milvus::v2::prelude::*;
let client = ClientV2::new(
&ConnectConfig::new().uri("YOUR_CLUSTER_ENDPOINT").token("YOUR_CLUSTER_TOKEN"),
)
.await?;
let request = QueryRequest::builder()
.collection_name("products")
.filter("category IS NULL")
.output_fields(["id"])
.limit(10)
.build()?;
let response = client.query(request).await?;
for row in response.results().rows()? {
println!("{:?}", row.get_i64("id")?);
}
#include <iostream>
#include <string>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
milvus::ConnectParam connect_param{"YOUR_CLUSTER_ENDPOINT"};
auto status = client->Connect(connect_param);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
auto request = milvus::QueryRequest()
.WithCollectionName("products")
.WithFilter("category IS NULL")
.AddOutputField("id")
.WithLimit(10);
milvus::QueryResponse response;
status = client->Query(request, response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const results = await client.query({
collection_name: "products",
filter: "category IS NULL",
output_fields: ["id"],
limit: 10,
});
console.log(results);
curl -X 'POST' \
'YOUR_CLUSTER_ENDPOINT/v2/vectordb/entities/query' \
-H 'accept: application/json' \
-H 'Authorization: Bearer YOUR_CLUSTER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"collectionName": "products",
"filter": "category IS NULL",
"outputFields": ["id"],
"limit": 10
}'
在同一个查询中替换 filter,即可检查任一字段,或组合多个条件:
| 过滤表达式 | 匹配的 ID | 用途 |
|---|---|---|
category IS NULL | 2 | 查找未设置分类的实体 |
category IS NOT NULL | 1、3 | 查找已设置分类的实体 |
embedding IS NULL | 3 | 查找没有向量的实体 |
embedding IS NOT NULL | 1、2 | 查找已有向量的实体 |
category IS NOT NULL AND embedding IS NOT NULL | 1 | 查找两个字段均已有值的实体 |
字段值如何判定
操作符检查的是字段实际存储的值。对于允许 NULL 值且未设置默认值的字段,插入时省略该字段或显式将其设置为 NULL,都会存储 NULL。配置默认值可能改变实际存储的值。详情请参阅可空字段和默认值。
| 字段类型 | NULL 判定规则 |
|---|---|
VARCHAR | 空字符串 "" 是非 NULL 值。 |
JSON | 整个字段的值为 NULL 时,匹配 IS NULL。{"category": null} 这样的 JSON 对象是非 NULL 值,即使其中某个键的值为 NULL。 |
ARRAY | 整个字段的值为 NULL 时,匹配 IS NULL。数组元素不能为 NULL,且 IS NULL / IS NOT NULL 不支持 tags[0] 这样的数组元素访问。请参阅 Array 类型。 |
| 普通向量类型 | NULL 表示向量值缺失。各分量均为零的向量不是 NULL。 |
对于定义为 nullable=False 的受支持字段,IS NULL 不匹配任何实体,IS NOT NULL 匹配所有可见实体。过滤表达式中的其他条件仍然生效。
在向量搜索中使用 NULL 过滤
这两个操作符也可以用于搜索过滤条件。不过,实体只有在被搜索的向量字段中有向量值,才能参与相似性搜索。
以上述数据为例,假设搜索指定了 anns_field="embedding":
| 过滤表达式 | 可参与相似性搜索的实体 | 原因 |
|---|---|---|
category IS NULL | 2 | 实体 2 没有分类,但有 embedding 向量。 |
embedding IS NULL | 无 | 实体 3 满足过滤条件,但没有可与查询向量比较的 embedding 向量。 |
embedding IS NOT NULL | 1、2 | 两个实体都有 embedding 向量。 |
这三个过滤表达式都是有效的。搜索 embedding 时,如果同时使用 embedding IS NULL 过滤,将没有命中结果,因为没有实体能同时满足“字段为 NULL”和“具有可用于比较的向量”这两个条件。要获取缺失向量的实体,请使用上文示例中的 query()。
向量搜索本身就会跳过被搜索的向量字段为 NULL 的实体,因此在搜索 embedding 时,embedding IS NOT NULL 不会进一步缩小候选范围。排序、其他过滤条件和搜索结果数量限制仍会决定最终返回哪些候选实体。
在 JSON 和 ARRAY 字段中使用基本操作符的注意事项
Zilliz Cloud 集群 中的基本操作符用途广泛,不仅适用于标量字段,也可以有效应用于 JSON 和 ARRAY 字段中的键和索引。
例如,如果 product 字段包含 price、model 和 tags 等多个键,应始终直接引用目标键:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'product["price"] > 1000'
String filter = "product[\"price\"] > 1000";
filter := "product[\"price\"] > 1000"
let filter = "product[\"price\"] > 1000";
std::string filter = "product[\"price\"] > 1000";
const filter = 'product["price"] > 1000';
filter='product["price"] > 1000'
要查找温度记录数组中第一个温度值超过指定数值的记录,可以使用:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- cURL
filter = 'history_temperatures[0] > 30'
String filter = "history_temperatures[0] > 30";
filter := "history_temperatures[0] > 30"
let filter = "history_temperatures[0] > 30";
std::string filter = "history_temperatures[0] > 30";
const filter = 'history_temperatures[0] > 30';
filter='history_temperatures[0] > 30'
总结
Zilliz Cloud 提供了多种基本操作符,使您可以灵活地过滤和查询数据。通过组合比较、范围、算术和逻辑操作符,您可以构建功能强大的过滤表达式,缩小搜索结果范围并高效检索所需数据。
常见问题
过滤条件中的匹配值列表是否有长度限制(例如 filter='color in ["red", "green", "blue"]')?列表过长时应该怎么办?
Zilliz Cloud 不限制过滤条件中匹配值列表的长度。但是,列表过长会显著影响查询性能。 如果过滤条件包含很长的匹配值列表,或包含大量元素的复杂表达式,建议使用过滤表达式模板来提升查询性能。