跳到主要内容
版本:v2.4.x

使用 JSON 字段

本指南介绍如何使用 JSON 字段,例如插入 JSON 值以及使用基本和高级操作符在 JSON 字段中搜索和查询。

概述

JSON 是 Javascript Object Notation 的缩写,是一种基于文本的轻量级简单数据格式。JSON 中的数据采用键值对结构,其中每个键都是一个字符串,可映射到数字、字符串、布尔、列表或数组的值。利用 Milvus 群集,可以将字典作为字段值存储在 Collection 中。

例如,以下代码会随机生成键值对,每个键值对都包含一个键值为颜色的 JSON 字段。

# 3. Insert randomly generated vectors
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(1000):
current_color = random.choice(colors)
current_tag = random.randint(1000, 9999)
current_coord = [ random.randint(0, 40) for _ in range(3) ]
current_ref = [ [ random.choice(colors) for _ in range(3) ] for _ in range(3) ]
data.append({
"id": i,
"vector": [ random.uniform(-1, 1) for _ in range(5) ],
"color": {
"label": current_color,
"tag": current_tag,
"coord": current_coord,
"ref": current_ref
}
})

print(data[0])

您可以通过查看第一个条目来查看生成数据的结构。

{
"id": 0,
"vector": [
-0.8017921296923975,
0.550046715206634,
0.764922589768134,
0.6371433836123146,
0.2705233937454232
],
"color": {
"label": "blue",
"tag": 9927,
"coord": [
22,
36,
6
],
"ref": [
[
"blue",
"green",
"white"
],
[
"black",
"green",
"pink"
],
[
"grey",
"black",
"brown"
]
]
}
}
说明

注意事项

  • 确保列表或数组中的所有值都是相同的数据类型。

  • JSON 字段值中的任何嵌套字典都将被视为字符串。

  • 仅使用字母数字字符和下划线来命名 JSON 键,因为其他字符可能会导致过滤或搜索出现问题。

  • 目前,还不能为 JSON 字段编制索引,这可能会导致过滤耗时。不过,这一限制将在即将发布的版本中得到解决。

定义 JSON 字段

要定义 JSON 字段,只需遵循与定义其他类型字段相同的步骤即可。

有关参数的更多信息,请参阅 MilvusClient, create_schema(), add_field(), add_index(), create_collection()get_load_state()在 SDK 参考资料中。

有关参数的更多信息,请参阅 MilvusClientV2, createSchema(), addField(), IndexParam, createCollection()getLoadState()在 SDK 参考资料中。

有关参数的更多信息,请参阅 MilvusClientcreateCollection()createCollection()

import random, time
from pymilvus import connections, MilvusClient, DataType

CLUSTER_ENDPOINT = "http://localhost:19530"

# 1. Set up a Milvus client
client = MilvusClient(
uri=CLUSTER_ENDPOINT
)

# 2. Create a collection
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=False,
)

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="color", datatype=DataType.JSON)

index_params = MilvusClient.prepare_index_params()

index_params.add_index(
field_name="id",
index_type="STL_SORT"
)

index_params.add_index(
field_name="vector",
index_type="IVF_FLAT",
metric_type="L2",
params={"nlist": 1024}
)

client.create_collection(
collection_name="test_collection",
schema=schema,
index_params=index_params
)

res = client.get_load_state(
collection_name="test_collection"
)

print(res)

# Output
#
# {
# "state": "<LoadState: Loaded>"
# }

有关参数的更多信息,请参阅 MilvusClient, create_schema(), add_field(), add_index(), create_collection()get_load_state()在 SDK 参考资料中。

有关参数的更多信息,请参阅 MilvusClientV2, createSchema(), addField(), IndexParam, createCollection()getLoadState()在 SDK 参考资料中。

有关参数的更多信息,请参阅 MilvusClient, createCollection()getLoadState()的更多信息。

插入字段值

CollectionSchema 对象创建一个 Collection 后,就可以向其中插入字典,如上面的字典。

使用 insert()方法将数据插入 Collection。

使用 insert()方法将数据插入 Collection。

使用 insert()方法将数据插入 Collection。

res = client.insert(
collection_name="test_collection",
data=data
)

print(res)

# Output
#
# {
# "insert_count": 1000,
# "ids": [
# 0,
# 1,
# 2,
# 3,
# 4,
# 5,
# 6,
# 7,
# 8,
# 9,
# "(990 more items hidden)"
# ]
# }

基本标量过滤

一旦添加了所有数据,就可以使用 JSON 字段中的键进行搜索和查询,方式与标准标量字段相同。

有关参数的更多信息,请参阅 search()有关参数的更多信息,请参阅 SDK 参考资料中的

有关参数的更多信息,请参阅 search()有关参数的更多信息,请参阅 SDK 参考资料中的

有关参数的更多信息,请参阅 search()有关参数的更多信息,请参阅 SDK 参考资料中的

# 4. Basic search with a JSON field
query_vectors = [ [ random.uniform(-1, 1) for _ in range(5) ]]

res = client.search(
collection_name="test_collection",
data=query_vectors,
filter='color["label"] in ["red"]',
search_params={
"metric_type": "L2",
"params": {"nprobe": 16}
},
output_fields=["id", "color"],
limit=3
)

print(res)

# Output
#
# [
# [
# {
# "id": 460,
# "distance": 0.4016231596469879,
# "entity": {
# "id": 460,
# "color": {
# "label": "red",
# "tag": 5030,
# "coord": [14, 32, 40],
# "ref": [
# [ "pink", "green", "brown" ],
# [ "red", "grey", "black"],
# [ "red", "yellow", "orange"]
# ]
# }
# }
# },
# {
# "id": 785,
# "distance": 0.451080858707428,
# "entity": {
# "id": 785,
# "color": {
# "label": "red",
# "tag": 5290,
# "coord": [31, 13, 23],
# "ref": [
# ["yellow", "pink", "pink"],
# ["purple", "grey", "orange"],
# ["grey", "purple", "pink"]
# ]
# }
# }
# },
# {
# "id": 355,
# "distance": 0.5839247703552246,
# "entity": {
# "id": 355,
# "color": {
# "label": "red",
# "tag": 8725,
# "coord": [5, 10, 22],
# "ref": [
# ["white", "purple", "yellow"],
# ["white", "purple", "white"],
# ["orange", "white", "pink"]
# ]
# }
# }
# }
# ]
# ]

高级标量过滤

Milvus 提供一组高级过滤器,用于在 JSON 字段中进行标量过滤。这些过滤器是JSON_CONTAINS,JSON_CONTAINS_ALL, 和JSON_CONTAINS_ANY

  • 过滤以["blue", "brown", "grey"] 作为参考颜色集的所有实体。

    # 5. Advanced search within a JSON field

    res = client.query(
    collection_name="test_collection",
    data=query_vectors,
    filter='JSON_CONTAINS(color["ref"], ["blue", "brown", "grey"])',
    output_fields=["id", "color"],
    limit=3
    )

    print(res)

    # Output
    #
    # [
    # {
    # "id": 79,
    # "color": {
    # "label": "orange",
    # "tag": 8857,
    # "coord": [
    # 10,
    # 14,
    # 5
    # ],
    # "ref": [
    # [
    # "yellow",
    # "white",
    # "green"
    # ],
    # [
    # "blue",
    # "purple",
    # "purple"
    # ],
    # [
    # "blue",
    # "brown",
    # "grey"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 371,
    # "color": {
    # "label": "black",
    # "tag": 1324,
    # "coord": [
    # 2,
    # 18,
    # 32
    # ],
    # "ref": [
    # [
    # "purple",
    # "orange",
    # "brown"
    # ],
    # [
    # "blue",
    # "brown",
    # "grey"
    # ],
    # [
    # "purple",
    # "blue",
    # "blue"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 590,
    # "color": {
    # "label": "red",
    # "tag": 3340,
    # "coord": [
    # 13,
    # 21,
    # 13
    # ],
    # "ref": [
    # [
    # "yellow",
    # "yellow",
    # "red"
    # ],
    # [
    # "blue",
    # "brown",
    # "grey"
    # ],
    # [
    # "pink",
    # "yellow",
    # "purple"
    # ]
    # ]
    # }
    # }
    # ]
  • 过滤具有[4, 5] 协调器的实体。

    res = client.query(
    collection_name="test_collection",
    data=query_vectors,
    filter='JSON_CONTAINS_ALL(color["coord"], [4, 5])',
    output_fields=["id", "color"],
    limit=3
    )

    print(res)

    # Output
    #
    # [
    # {
    # "id": 281,
    # "color": {
    # "label": "red",
    # "tag": 3645,
    # "coord": [
    # 5,
    # 33,
    # 4
    # ],
    # "ref": [
    # [
    # "orange",
    # "blue",
    # "pink"
    # ],
    # [
    # "purple",
    # "blue",
    # "purple"
    # ],
    # [
    # "black",
    # "brown",
    # "yellow"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 464,
    # "color": {
    # "label": "brown",
    # "tag": 6261,
    # "coord": [
    # 5,
    # 9,
    # 4
    # ],
    # "ref": [
    # [
    # "purple",
    # "purple",
    # "brown"
    # ],
    # [
    # "black",
    # "pink",
    # "white"
    # ],
    # [
    # "brown",
    # "grey",
    # "brown"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 567,
    # "color": {
    # "label": "green",
    # "tag": 4589,
    # "coord": [
    # 5,
    # 39,
    # 4
    # ],
    # "ref": [
    # [
    # "purple",
    # "yellow",
    # "white"
    # ],
    # [
    # "yellow",
    # "yellow",
    # "brown"
    # ],
    # [
    # "blue",
    # "red",
    # "yellow"
    # ]
    # ]
    # }
    # }
    # ]
  • 过滤协调器包含45 的实体。

    res = client.query(
    collection_name="test_collection",
    data=query_vectors,
    filter='JSON_CONTAINS_ANY(color["coord"], [4, 5])',
    output_fields=["id", "color"],
    limit=3
    )

    print(res)

    # Output
    #
    # [
    # {
    # "id": 0,
    # "color": {
    # "label": "yellow",
    # "tag": 6340,
    # "coord": [
    # 40,
    # 4,
    # 40
    # ],
    # "ref": [
    # [
    # "purple",
    # "yellow",
    # "orange"
    # ],
    # [
    # "green",
    # "grey",
    # "purple"
    # ],
    # [
    # "black",
    # "white",
    # "yellow"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 2,
    # "color": {
    # "label": "brown",
    # "tag": 9359,
    # "coord": [
    # 38,
    # 21,
    # 5
    # ],
    # "ref": [
    # [
    # "red",
    # "brown",
    # "white"
    # ],
    # [
    # "purple",
    # "red",
    # "brown"
    # ],
    # [
    # "pink",
    # "grey",
    # "black"
    # ]
    # ]
    # }
    # },
    # {
    # "id": 7,
    # "color": {
    # "label": "green",
    # "tag": 3560,
    # "coord": [
    # 5,
    # 9,
    # 5
    # ],
    # "ref": [
    # [
    # "blue",
    # "orange",
    # "green"
    # ],
    # [
    # "blue",
    # "blue",
    # "black"
    # ],
    # [
    # "green",
    # "purple",
    # "green"
    # ]
    # ]
    # }
    # }
    # ]

JSON 过滤器参考

在处理 JSON 字段时,可以将 JSON 字段用作过滤器,也可以使用其中的某些特定键。

说明

注意

  • Milvus 将字符串值原样保存在 JSON 字段中,而不执行语义转义或转换。

例如,'a"b'"a'b"'a\\\\'b'"a\\\\"b" 将按原样保存,而'a'b'"a"b" 将被视为无效值。

  • 要使用 JSON 字段构建过滤表达式,可以利用字段中的键。

  • 如果键值是整数或浮点数,则可以将其与另一个整数或浮点数键值或 INT32/64 或 FLOAT32/64 字段进行比较。

  • 如果键值是字符串,则只能与另一个字符串键或 VARCHAR 字段进行比较。

JSON 字段中的基本操作符

下表假定名为json_key 的 JSON 字段的值有一个名为A 的键。在使用 JSON 字段键构建布尔表达式时,请将其作为参考。

操作符示例备注
<'json_field["A"] < 3'如果json_field["A"] 的值小于3 ,则该表达式的值为 true。
&gt;'json_field["A"] > 1'如果json_field["A"] 的值大于1 ,则此表达式的值为 true。
=='json_field["A"] == 1'如果json_field["A"] 的值等于1 ,则此表达式的值为真。
!='json_field["A"][0]' != "abc"'如果
-json_field 没有名为A 的键,则此表达式的值为真。
-json_field 有一个名为A 的键,但json_field["A"] 不是数组。
-json_field["A"] 是一个空数组。
-json_field["A"] 是一个数组,但第一个元素不是abc
<='json_field["A"] <= 5'如果json_field["A"] 的值小于或等于5 ,则此表达式的值为 true。
&gt;='json_field["A"] >= 1'如果json_field["A"] 的值大于或等于1 ,则此表达式的值为真。
'not json_field["A"] == 1'如果
-json_field 没有名为A 的键,则此表达式的值为真。
-json_field["A"] 不等于1.
'json_field["A"] in [1, 2, 3]'如果json_field["A"] 的值是1,23 ,则此表达式的值为 true。
和 (&&)'json_field["A"] > 1 && json_field["A"] < 3'如果json_field["A"] 的值大于 1 且小于3 ,则此表达式的值为 true。
**或 ()**
存在'exists json_field["A"]'如果json_field 有一个名为A 的键,则此表达式的值为真。

高级操作符

以下操作符专门针对 JSON 字段:

  • json_contains(identifier, jsonExpr)

    此操作符可过滤标识符包含指定 JSON 表达式的实体。

    • 例 1:{"x": [1,2,3]}

      json_contains(x, 1) # => True (x contains 1.)
      json_contains(x, "a") # => False (x does not contain a member "a".)
    • 例 2:{"x", [[1,2,3], [4,5,6], [7,8,9]]}

      json_contains(x, [1,2,3]) # => True (x contains [1,2,3].)
      json_contains(x, [3,2,1]) # => False (x does contain a member [3,2,1].)
  • json_contains_all(identifier, jsonExpr)

    该操作符可过滤标识符包含 JSON 表达式所有成员的实体。

    示例{"x": [1,2,3,4,5,7,8]}

    json_contains_all(x, [1,2,8]) # => True (x contains 1, 2, and 8.)
    json_contains_all(x, [4,5,6]) # => False (x does not has a member 6.)
  • json_contains_any(identifier, jsonExpr)

    此操作符可过滤标识符包含 JSON 表达式中任何成员的实体。

    示例{"x": [1,2,3,4,5,7,8]}

    json_contains_any(x, [1,2,8]) # => True (x contains 1, 2, and 8.)
    json_contains_any(x, [4,5,6]) # => True (x contains 4 and 5.)
    json_contains_any(x, [6,9]) # => False (x contains none of 6 and 9.)