Milvus(23):过滤

Milvus 提供强大的过滤功能,可精确查询数据。过滤表达式允许你针对特定的标量字段,用不同的条件细化搜索结果。

1 算术操作符

Milvus 提供丰富的基本操作符,帮助您高效地过滤和查询数据。这些操作符允许您根据标量字段、数字计算、逻辑条件等来完善搜索条件。了解如何使用这些操作符对于建立精确查询和最大限度地提高搜索效率至关重要。

1.1 比较操作符

比较操作符用于根据相等、不等或大小过滤数据。它们适用于数字和文本字段。

  • == 等于
  • != (不等于)
  • > 大于
  • < 小于
  • >= (大于或等于)
  • <= (小于或等于)

假设有一个名为status 的字段,您想查找status 为 "活动 "的所有实体。您可以使用相等操作符==

python 复制代码
filter = 'status == "active"'

查找status 不是 "非活动 "的实体:

python 复制代码
filter = 'status != "inactive"'

如果要查找age 大于 30 的所有实体:

python 复制代码
filter = 'age > 30'

要查找price 小于 100 的实体:

python 复制代码
filter = 'price < 100'

如果要查找rating 大于或等于 4 的所有实体:

python 复制代码
filter = 'rating >= 4'

要查找discount 小于或等于 10% 的实体:

python 复制代码
filter = 'discount <= 10'

1.2 范围操作符

范围操作符有助于根据特定的值集或范围过滤数据。

  • IN:用于匹配特定集合或范围内的值。
  • LIKE:用于匹配模式(主要用于文本字段)。

如果要查找color 为 "红色"、"绿色 "或 "蓝色 "的所有实体:

python 复制代码
filter = 'color in ["red", "green", "blue"]'

LIKE 操作符用于字符串字段中的模式匹配。它可以匹配文本中不同位置的子串:前缀后缀和词缀LIKE 操作符使用% 符号作为通配符,可以匹配任意数量的字符(包括 0)。

要执行前缀 匹配,即字符串以给定的模式开始,可以将模式放在开头,然后使用% 匹配其后的任何字符。例如,要查找name 以 "Prod "开头的所有产品:

python 复制代码
filter = 'name LIKE "Prod%"'

后缀 匹配中,如果字符串以给定的模式结尾,则将% 符号放在模式的开头。例如,查找name 以 "XYZ "结尾的所有产品:

python 复制代码
filter = 'name LIKE "%XYZ"'

要执行词缀 匹配,即模式可以出现在字符串的任何位置,可以在模式的开头和结尾处都加上% 符号。例如,要查找name 中包含 "Pro "一词的所有产品:

python 复制代码
filter = 'name LIKE "%Pro%"'

1.3 算术操作符

算术操作符允许您根据涉及数字字段的计算创建条件。

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 模乘
  • **

查找id 是偶数(即能被 2 整除)的实体:

python 复制代码
filter = 'id % 2 == 0'

查找price 升为 2 的幂大于 1000 的实体:

python 复制代码
filter = 'price ** 2 > 1000'

1.4 逻辑操作符

逻辑操作符用于将多个条件组合成更复杂的过滤表达式。这些运算符包括AND,OR, 和NOT

  • AND:组合必须全部为真的多个条件。
  • OR:组合至少一个必须为真的条件。
  • NOT:否定一个条件。

查找price 大于 100 且stock 大于 50 的所有产品:

python 复制代码
filter = 'price > 100 AND stock > 50'

查找color 为 "红色 "或 "蓝色 "的所有产品:

python 复制代码
filter = 'color == "red" OR color == "blue"'

查找color 不是 "绿色 "的所有产品:

python 复制代码
filter = 'NOT color == "green"'

1.5 IS NULL 和 IS NOT NULL 操作符

IS NULLIS NOT NULL 操作符用于根据字段是否包含空值(无数据)过滤字段。操作符不区分大小写,因此可以使用IS NULLis null ,以及IS NOT NULLis not null

  • IS NULL:识别特定字段包含空值(即值不存在或未定义)的实体。
  • IS NOT NULL:识别特定字段包含除空值以外的任何值的实体,即字段具有有效的定义值。

1.5.1 具有空值的正则标量字段

Milvus 允许过滤带空值的常规标量字段,如字符串或数字。空字符串"" 不会被视为VARCHAR 字段的空值。

检索description 字段为空值的实体:

python 复制代码
filter = 'description IS NULL'

检索description 字段不是空值的实体:

python 复制代码
filter = 'description IS NOT NULL'

检索description 字段不是空值且price 字段大于 10 的实体:

python 复制代码
filter = 'description IS NOT NULL AND price > 10'

1.5.2 具有空值的 JSON 字段

Milvus 允许过滤包含空值的 JSON 字段。在以下情况下,JSON 字段会被视为空值:

  • 整个 JSON 对象被明确设置为 None(空),例如{"metadata": None}
  • 实体中完全没有 JSON 字段。

如果 JSON 对象中的某些元素为空(如单个键),则字段仍被视为非空。例如,尽管category 关键字为空,但\{"metadata": \{"category": None, "price": 99.99}} 不会被视为空字段。为进一步说明 Milvus 如何处理带有空值的 JSON 字段,请考虑以下带有 JSON 字段metadata 的示例数据:

python 复制代码
data = [
  {
      "metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
      "pk": 1,
      "embedding": [0.12, 0.34, 0.56]
  },
  {
      "metadata": None, # 整个JSON对象为空
      "pk": 2,
      "embedding": [0.56, 0.78, 0.90]
  },
  {  # JSON字段' metadata '完全丢失
      "pk": 3,
      "embedding": [0.91, 0.18, 0.23]
  },
  {
      "metadata": {"category": None, "price": 99.99, "brand": "BrandA"}, # 单个键值为空
      "pk": 4,
      "embedding": [0.56, 0.38, 0.21]
  }
]

查找metadata 字段丢失或明确设置为 "无 "的实体:

python 复制代码
filter = 'metadata IS NULL'

# Example output:
# data: [
#     "{'metadata': None, 'pk': 2}",
#     "{'metadata': None, 'pk': 3}"
# ]

查找metadata 字段不是空值的实体:

python 复制代码
filter = 'metadata IS NOT NULL'

# Example output:
# data: [
#     "{'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}, 'pk': 1}",
#     "{'metadata': {'category': None, 'price': 99.99, 'brand': 'BrandA'}, 'pk': 4}"
# ]

1.5.3 具有空值的 ARRAY 字段

Milvus 允许过滤包含空值的 ARRAY 字段。ARRAY 字段在以下情况下被视为空值:

  • 整个 ARRAY 字段明确设置为 None(空),例如"tags": None
  • 实体中完全没有 ARRAY 字段。

ARRAY 字段不能包含部分空值,因为 ARRAY 字段中的所有元素必须具有相同的数据类型。为进一步说明 Milvus 如何处理带有空值的 ARRAY 字段,请考虑以下带有 ARRAY 字段tags 的示例数据:

python 复制代码
data = [
  {
      "tags": ["pop", "rock", "classic"],
      "ratings": [5, 4, 3],
      "pk": 1,
      "embedding": [0.12, 0.34, 0.56]
  },
  {
      "tags": None,  # 整个数组为空
      "ratings": [4, 5],
      "pk": 2,
      "embedding": [0.78, 0.91, 0.23]
  },
  {  # 标签字段完全缺失
      "ratings": [9, 5],
      "pk": 3,
      "embedding": [0.18, 0.11, 0.23]
  }
]

检索tags 字段丢失或明确设置为None 的实体:

python 复制代码
filter = 'tags IS NULL'

# Example output:
# data: [
#     "{'tags': None, 'ratings': [4, 5], 'embedding': [0.78, 0.91, 0.23], 'pk': 2}",
#     "{'tags': None, 'ratings': [9, 5], 'embedding': [0.18, 0.11, 0.23], 'pk': 3}"
# ]

检索tags 字段不为空的实体:

python 复制代码
filter = 'tags IS NOT NULL'

# Example output:
# data: [
#     "{'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}, 'pk': 1}",
#     "{'metadata': {'category': None, 'price': 99.99, 'brand': 'BrandA'}, 'pk': 4}"
# ]

1.6 在 JSON 和 ARRAY 字段中使用基本操作符的提示

虽然 Milvus 的基本操作符用途广泛,可以应用于标量字段,但它们也可以有效地用于 JSON 和 ARRAY 字段中的键和索引。例如,如果product 字段包含多个键,如pricemodeltags ,则始终直接引用键:

python 复制代码
filter = 'product["price"] > 1000'

要查找记录温度的数组中第一个温度超过特定值的记录,请使用:

python 复制代码
filter = 'history_temperatures[0] > 30'

2 过滤器模板

在 Milvus 中,包含大量元素的复杂过滤表达式,尤其是那些涉及非 ASCII 字符(如中日韩字符)的表达式,会严重影响查询性能。为了解决这个问题,Milvus 引入了过滤表达式模板机制,旨在通过减少解析复杂表达式所花费的时间来提高效率。本页介绍了在搜索、查询和删除操作中使用过滤表达式模板的方法。

2.1 概述

过滤表达式模板化允许你创建带有占位符的过滤表达式,这些占位符可以在查询执行过程中动态替换为值。使用模板,可以避免直接在过滤器中嵌入大型数组或复杂表达式,从而减少解析时间并提高查询性能。

假设有一个涉及两个字段agecity 的过滤器表达式,要查找所有年龄大于 25 岁且居住在 "北京"或 "上海"的人。您可以使用模板来代替直接在筛选表达式中嵌入值:

python 复制代码
filter = "age > {age} AND city IN {city}"
filter_params = {"age": 25, "city": ["北京", "上海"]}

在这里,{age}{city} 是占位符,在执行查询时将被替换为filter_params 中的实际值。在 Milvus 中使用过滤表达式模板有几个主要优点:

  • 减少解析时间:通过用占位符替换大型或复杂的过滤器表达式,系统可以减少解析和处理过滤器的时间。
  • 提高查询性能:解析开销减少后,查询性能就会提高,从而获得更高的 QPS 和更快的响应时间。
  • 可扩展性:随着数据集的增长和过滤器表达式的复杂化,模板化可确保性能保持高效和可扩展。

2.2 搜索操作符

对于 Milvus 中的搜索操作,filter 表达式用于定义过滤条件,filter_params 参数用于指定占位符的值。filter_params 字典包含 Milvus 将用于代入过滤表达式的动态值。在本例中,Milvus 将在执行搜索时用25 动态替换{age} ,用["北京", "上海"] 动态替换{city}

python 复制代码
expr = "age > {age} AND city IN {city}"
filter_params = {"age": 25, "city": ["北京", "上海"]}
res = client.search(
    "hello_milvus",
    vectors[:nq],
    filter=expr,
    limit=10,
    output_fields=["age", "city"],
    search_params={"metric_type": "COSINE", "params": {"search_list": 100}},
    filter_params=filter_params,
)

2.3 查询操作符

同样的模板机制也可应用于 Milvus 的查询操作符。在query 函数中,您可以定义过滤表达式,并使用filter_params 指定要替换的值。通过使用filter_params ,Milvus 可以有效处理值的动态插入,提高查询执行速度。

python 复制代码
expr = "age > {age} AND city IN {city}"
filter_params = {"age": 25, "city": ["北京", "上海"]}
res = client.query(
    "hello_milvus",
    filter=expr,
    output_fields=["age", "city"],
    filter_params=filter_params
)

2.4 删除操作符

在删除操作中也可以使用过滤表达式模板。与搜索和查询类似,filter 表达式定义条件,filter_params 为占位符提供动态值。这种方法可以提高删除操作的性能,尤其是在处理复杂的过滤条件时。

python 复制代码
expr = "age > {age} AND city IN {city}"
filter_params = {"age": 25, "city": ["北京", "上海"]}
res = client.delete(
    "hello_milvus",
    filter=expr,
    filter_params=filter_params
)

3 JSON 操作符

Milvus 支持用于查询和过滤 JSON 字段的高级操作符,使其成为管理复杂结构化数据的完美工具。这些操作符可实现对 JSON 文档的高效查询,允许您根据 JSON 字段中的特定元素、值或条件检索实体。

JSON 字段无法处理复杂的嵌套结构,而是将所有嵌套结构视为纯字符串。因此,在使用 JSON 字段时,建议避免过深的嵌套,并确保数据结构尽可能扁平,以获得最佳性能。

3.1 可用的 JSON 操作符

Milvus 提供了几个强大的 JSON 操作符,帮助过滤和查询 JSON 数据,这些操作符是

  • JSON_CONTAINS(identifier, expr):过滤在字段中找到指定 JSON 表达式的实体。
  • JSON_CONTAINS_ALL(identifier, expr):确保字段中包含指定 JSON 表达式的所有元素。
  • JSON_CONTAINS_ANY(identifier, expr):筛选字段中至少存在一个 JSON 表达式成员的实体。

3.2 JSON_CONTAINS

json_contains 操作符检查 JSON 字段中是否存在特定元素或子阵。当你想确保一个 JSON 数组或对象包含一个特定值时,它就非常有用了。假设您有一个产品 Collections,每个 Collections 都有一个tags 字段,其中包含一个由字符串组成的 JSON 数组,如["electronics", "sale", "new"] 。您想过滤带有"sale" 标记的产品。

python 复制代码
# JSON data: {"tags": ["electronics", "sale", "new"]}
filter = 'json_contains(product["tags"], "sale")'

在此示例中,Milvus 将返回tags 字段包含"sale" 元素的所有产品。

3.3 json_contains_all

json_contains_all 操作符可确保目标字段中包含指定 JSON 表达式的所有元素。当需要匹配 JSON 数组中的多个值时,该操作符尤其有用。继续使用产品标记方案,如果要查找具有"electronics""sale""new" 标记的所有产品,可以使用json_contains_all 操作符。

python 复制代码
# JSON data: {"tags": ["electronics", "sale", "new", "discount"]}
filter = 'json_contains_all(product["tags"], ["electronics", "sale", "new"])'

此查询将返回tags 数组包含所有三个指定元素的所有产品:"electronics","sale", 和"new"

3.4 json_contains_any

json_contains_any 操作符可过滤字段中至少存在一个 JSON 表达式成员的实体。当您想根据多个可能值中的任意一个值来匹配实体时,该操作符非常有用。假设您想过滤至少有一个标签"electronics","sale", 或"new" 的产品。您可以使用json_contains_any 操作符来实现这一目的。

python 复制代码
# JSON data: {"tags": ["electronics", "sale", "new"]}
filter = 'json_contains_any(tags, ["electronics", "new", "clearance"])'

在这种情况下,Milvus 将返回列表["electronics", "new", "clearance"] 中至少有一个标签的所有产品。即使产品只有其中一个标签,也会包含在结果中。

4 数组操作符

Milvus 提供功能强大的操作符来查询数组字段,允许你根据数组内容过滤和检索实体。数组中的所有元素必须是同一类型,数组中的嵌套结构将被视为纯字符串。因此,在使用 ARRAY 字段时,最好避免过深的嵌套,并确保数据结构尽可能扁平,以获得最佳性能。

4.1 可用的 ARRAY 操作符

ARRAY 操作符允许在 Milvus 中对数组字段进行精细查询。这些操作符包括

  • ARRAY_CONTAINS(identifier, expr):检查数组字段中是否存在特定元素。
  • ARRAY_CONTAINS_ALL(identifier, expr):确保指定列表中的所有元素都存在于数组字段中。
  • ARRAY_CONTAINS_ANY(identifier, expr):检查指定列表中的任何元素是否存在于数组字段中。
  • ARRAY_LENGTH(identifier, expr)ARRAY_COTAINS:允许根据数组字段中元素的数量过滤实体。

4.2 ARRAY_CONTAINS

ARRAY_CONTAINS 操作符用于检查数组字段中是否存在特定元素。当您想查找数组中存在给定元素的实体时,它非常有用。假设有一个数组字段history_temperatures ,其中包含不同年份的最低气温记录。要查找数组中包含值23 的所有实体,可以使用以下过滤表达式:

python 复制代码
filter = 'ARRAY_CONTAINS(history_temperatures, 23)'

这将返回history_temperatures 数组包含23 值的所有实体。

4.3 array_contains_all

ARRAY_CONTAINS_ALL 操作符可确保指定列表中的所有元素都出现在数组字段中。当您要匹配数组中包含多个值的实体时,此操作符非常有用。如果要查找history_temperatures 数组同时包含2324 的所有实体,可以使用 :

python 复制代码
filter = 'ARRAY_CONTAINS_ALL(history_temperatures, [23, 24])'

这将返回history_temperatures 数组同时包含指定值的所有实体。

4.4 array_contains_any

ARRAY_CONTAINS_ANY 操作符会检查数组字段中是否存在指定列表中的任何元素。当您想匹配数组中至少包含一个指定值的实体时,此操作非常有用。要查找history_temperatures 数组包含2324 的所有实体,可以使用 :

python 复制代码
filter = 'ARRAY_CONTAINS_ANY(history_temperatures, [23, 24])'

这将返回history_temperatures 数组包含2324 中至少一个值的所有实体。

4.5 ARRAY_LENGTH

ARRAY_LENGTH 操作符允许您根据数组字段中元素的数量过滤实体。这在需要查找具有一定长度数组的实体时非常有用。如果要查找history_temperatures 数组中元素少于 10 个的所有实体,可以使用:

python 复制代码
filter = 'ARRAY_LENGTH(history_temperatures) < 10'

这将返回history_temperatures 数组中元素少于 10 个的所有实体。

相关推荐
咕噜企业分发小米20 小时前
阿里云Milvus的HNSW索引如何优化?
阿里云·云计算·milvus
咕噜企业分发小米20 小时前
阿里云Milvus支持哪些向量检索算法?
算法·机器学习·milvus
lusasky20 小时前
Milvus为什么需要MinIO
milvus
学Linux的语莫20 小时前
向量数据库milvus的搭建部署
milvus
咕噜企业分发小米21 小时前
阿里云Milvus如何评估向量检索效果?
阿里云·云计算·milvus
我在北国不背锅2 天前
Milvus向量数据库索引说明
数据库·milvus
杨二K2 天前
Milvus性能权衡
数据库·人工智能·milvus
IT_Octopus7 天前
Milvus IllegalAccessError:com.google.protobuf.LazyStringArrayList.emptyList()
milvus
ShadowSmartMicros8 天前
java调用milvus数据库
java·数据库·milvus
csdn5659738509 天前
阿里云 Milvus 轻松实现文搜图&图搜图
阿里云·云计算·milvus