Utilizar campos JSON
Este guia explica como utilizar os campos JSON, como inserir valores JSON, bem como pesquisar e consultar campos JSON com operadores básicos e avançados.
Visão geral
JSON significa Javascript Object Notation, que é um formato de dados leve e simples baseado em texto. Os dados em JSON são estruturados em pares chave-valor, onde cada chave é uma string que mapeia para um valor de um número, string, booleano, lista ou array. Com os clusters Milvus, é possível armazenar dicionários como um valor de campo em colecções.
Por exemplo, o código a seguir gera aleatoriamente pares de valores chave, cada um contendo um campo JSON com a cor chave.
# 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])
import java.util.*;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
// 3. Insert randomly generated vectors and JSON data into the collection
List<String> colors = Arrays.asList("green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey");
List<JsonObject> data = new ArrayList<>();
Gson gson = new Gson();
Random rand = new Random();
for (int i=0; i<1000; i++) {
String current_color = colors.get(rand.nextInt(colors.size()-1));
Integer current_tag = rand.nextInt(8999) + 1000;
List<Integer> current_coord = Arrays.asList(rand.nextInt(40), rand.nextInt(40), rand.nextInt(40));
List<List<String>> current_ref = Arrays.asList(
Arrays.asList(colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1))),
Arrays.asList(colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1))),
Arrays.asList(colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1)), colors.get(rand.nextInt(colors.size()-1)))
);
JsonObject row = new JsonObject();
row.addProperty("id", (long) i);
row.add("vector", gson.toJsonTree(Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat())));
JsonObject color = new JsonObject();
color.addProperty("label", current_color);
color.addProperty("tag", current_tag);
color.add("coord", gson.toJsonTree(current_coord));
color.add("ref", gson.toJsonTree(current_ref));
row.add("color", color);
data.add(row);
}
System.out.println(data.get(0));
// 3. Insert randomly generated vectors
const colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
var data = []
for (let i = 0; i < 1000; i++) {
const current_color = colors[Math.floor(Math.random() * colors.length)]
const current_tag = Math.floor(Math.random() * 8999 + 1000)
const current_coord = Array(3).fill(0).map(() => Math.floor(Math.random() * 40))
const current_ref = [ Array(3).fill(0).map(() => colors[Math.floor(Math.random() * colors.length)]) ]
data.push({
id: i,
vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
color: {
label: current_color,
tag: current_tag,
coord: current_coord,
ref: current_ref
}
})
}
console.log(data[0])
Você pode visualizar a estrutura dos dados gerados verificando sua primeira entrada.
{
"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"
]
]
}
}
notas
Certifique-se de que todos os valores numa lista ou matriz são do mesmo tipo de dados.
Quaisquer dicionários aninhados num valor de campo JSON serão considerados cadeias de caracteres.
Utilize apenas caracteres alfanuméricos e sublinhados para nomear chaves JSON, uma vez que outros caracteres podem causar problemas de filtragem ou pesquisa.
- Atualmente, a indexação de campos JSON não está disponível, o que pode tornar a filtragem morosa. No entanto, esta limitação será resolvida nas próximas versões.
Definir campo JSON
Para definir um campo JSON, basta seguir o mesmo procedimento que para definir campos de outros tipos.
Para mais informações sobre parâmetros, consulte MilvusClient
, create_schema()
, add_field()
, add_index()
, create_collection()
, e get_load_state()
na referência do SDK.
Para mais informações sobre os parâmetros, consulte MilvusClientV2
, createSchema()
, addField()
, IndexParam
, createCollection()
, e getLoadState()
na referência do SDK.
Para mais informações sobre os parâmetros, consulte MilvusClient
e createCollection()
e createCollection()
na referência do SDK.
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>"
# }
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.*;
import io.milvus.v2.service.vector.request.*;
import io.milvus.v2.service.vector.request.data.*;
import io.milvus.v2.service.vector.response.*;
String CLUSTER_ENDPOINT = "http://localhost:19530";
// 1. Connect to Milvus server
ConnectConfig connectConfig = ConnectConfig.builder()
.uri(CLUSTER_ENDPOINT)
.build();
MilvusClientV2 client = new MilvusClientV2(connectConfig);
// 2. Create a collection in customized setup mode
// 2.1 Create schema
CreateCollectionReq.CollectionSchema schema = client.createSchema();
// 2.2 Add fields to schema
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.autoID(false)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("color")
.dataType(DataType.JSON)
.build());
// 2.3 Prepare index parameters
IndexParam indexParamForIdField = IndexParam.builder()
.fieldName("id")
.indexType(IndexParam.IndexType.STL_SORT)
.build();
Map<String, Object> params = new HashMap<>();
params.put("nlist", 1024);
IndexParam indexParamForVectorField = IndexParam.builder()
.fieldName("vector")
.indexType(IndexParam.IndexType.IVF_FLAT)
.metricType(IndexParam.MetricType.IP)
.extraParams(params)
.build();
List<IndexParam> indexParams = new ArrayList<>();
indexParams.add(indexParamForIdField);
indexParams.add(indexParamForVectorField);
// 2.4 Create a collection with schema and index parameters
CreateCollectionReq customizedSetupReq = CreateCollectionReq.builder()
.collectionName("test_collection")
.collectionSchema(schema)
.indexParams(indexParams)
.build();
client.createCollection(customizedSetupReq);
// 2.5 Check if the collection is loaded
GetLoadStateReq getLoadStateReq = GetLoadStateReq.builder()
.collectionName("test_collection")
.build();
Boolean isLoaded = client.getLoadState(getLoadStateReq);
System.out.println(isLoaded);
// Output:
// true
const { MilvusClient, DataType, sleep } = require("@zilliz/milvus2-sdk-node")
const address = "http://localhost:19530"
async function main() {
// 1. Set up a Milvus Client
client = new MilvusClient({address});
// 2. Create a collection
// 2.1 Define fields
const fields = [
{
name: "id",
data_type: DataType.Int64,
is_primary_key: true,
auto_id: false
},
{
name: "vector",
data_type: DataType.FloatVector,
dim: 5
},
{
name: "color",
data_type: DataType.JSON,
}
]
// 2.2 Prepare index parameters
const index_params = [{
field_name: "vector",
index_type: "IVF_FLAT",
metric_type: "IP",
params: { nlist: 1024}
}]
// 2.3 Create a collection with fields and index parameters
res = await client.createCollection({
collection_name: "test_collection",
fields: fields,
index_params: index_params
})
console.log(res.error_code)
// Output
//
// Success
//
res = await client.getLoadState({
collection_name: "test_collection",
})
console.log(res.state)
// Output
//
// LoadStateLoaded
//
Para mais informações sobre os parâmetros, consulte MilvusClient
, create_schema()
, add_field()
, add_index()
, create_collection()
, e get_load_state()
na referência do SDK.
Para mais informações sobre os parâmetros, consulte MilvusClientV2
, createSchema()
, addField()
, IndexParam
, createCollection()
, e getLoadState()
na referência do SDK.
Para mais informações sobre os parâmetros, consulte MilvusClient
, createCollection()
, e getLoadState()
na referência do SDK.
Inserir valores de campo
Após a criação de uma coleção a partir do objeto CollectionSchema
, podem ser inseridos dicionários como o que se encontra acima.
Utilize o método insert()
para inserir os dados na coleção.
Utilize o método insert()
para inserir os dados na coleção.
Utilizar o método insert()
para inserir os dados na coleção.
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)"
# ]
# }
// 3.1 Insert data into the collection
InsertReq insertReq = InsertReq.builder()
.collectionName("test_collection")
.data(data)
.build();
InsertResp insertResp = client.insert(insertReq);
System.out.println(insertResp.getInsertCnt());
// Output:
// 1000
// 3. Insert randomly generated vectors
const colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
var data = []
for (let i = 0; i < 1000; i++) {
const current_color = colors[Math.floor(Math.random() * colors.length)]
const current_tag = Math.floor(Math.random() * 8999 + 1000)
const current_coord = Array(3).fill(0).map(() => Math.floor(Math.random() * 40))
const current_ref = [ Array(3).fill(0).map(() => colors[Math.floor(Math.random() * colors.length)]) ]
data.push({
id: i,
vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
color: {
label: current_color,
tag: current_tag,
coord: current_coord,
ref: current_ref
}
})
}
console.log(data[0])
// Output
//
// {
// id: 0,
// vector: [
// 0.11455530974226114,
// 0.21704086958595314,
// 0.9430119822312437,
// 0.7802712923612023,
// 0.9106927960926137
// ],
// color: { label: 'grey', tag: 7393, coord: [ 22, 1, 22 ], ref: [ [Array] ] }
// }
//
res = await client.insert({
collection_name: "test_collection",
data: data,
})
console.log(res.insert_cnt)
// Output
//
// 1000
//
Filtragem escalar básica
Depois de todos os seus dados terem sido adicionados, pode efetuar pesquisas e consultas utilizando as chaves no campo JSON da mesma forma que faria com um campo escalar padrão.
Para obter mais informações sobre parâmetros, consulte search()
na referência do SDK.
Para obter mais informações sobre parâmetros, consulte search()
na referência do SDK.
Para obter mais informações sobre parâmetros, consultar search()
na referência do 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"]
# ]
# }
# }
# }
# ]
# ]
// 4. Search with partition key
List<BaseVector> query_vectors = Collections.singletonList(new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f}));
SearchReq searchReq = SearchReq.builder()
.collectionName("test_collection")
.data(query_vectors)
.filter("color[\"label\"] in [\"red\"]")
.outputFields(Arrays.asList("id", "color"))
.topK(3)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output:
// SearchResp.SearchResult(entity={color={"label":"red","tag":1018,"coord":[3,30,1],"ref":[["yellow","brown","orange"],["yellow","purple","blue"],["green","purple","purple"]]}, id=295}, score=1.1190735, id=295)
// SearchResp.SearchResult(entity={color={"label":"red","tag":8141,"coord":[38,31,29],"ref":[["blue","white","white"],["green","orange","green"],["yellow","green","black"]]}, id=667}, score=1.0679582, id=667)
// SearchResp.SearchResult(entity={color={"label":"red","tag":6837,"coord":[29,9,8],"ref":[["green","black","blue"],["purple","white","green"],["red","blue","black"]]}, id=927}, score=1.0029297, id=927)
// 4. Basic search with a JSON field
query_vectors = [[0.6765405125697714, 0.759217474274025, 0.4122471841491111, 0.3346805565394215, 0.09679748345514638]]
res = await client.search({
collection_name: "test_collection",
data: query_vectors,
filter: 'color["label"] in ["red"]',
output_fields: ["color", "id"],
limit: 3
})
console.log(JSON.stringify(res.results, null, 4))
// Output
//
// [
// {
// "score": 1.777988076210022,
// "id": "595",
// "color": {
// "label": "red",
// "tag": 7393,
// "coord": [31,34,18],
// "ref": [
// ["grey", "white", "orange"]
// ]
// }
// },
// {
// "score": 1.7542595863342285,
// "id": "82",
// "color": {
// "label": "red",
// "tag": 8636,
// "coord": [4,37,29],
// "ref": [
// ["brown", "brown", "pink"]
// ]
// }
// },
// {
// "score": 1.7537562847137451,
// "id": "748",
// "color": {
// "label": "red",
// "tag": 1626,
// "coord": [31,4,25
// ],
// "ref": [
// ["grey", "green", "blue"]
// ]
// }
// }
// ]
//
Filtragem escalar avançada
O Milvus fornece um conjunto de filtros avançados para filtragem escalar em campos JSON. Estes filtros são JSON_CONTAINS
, JSON_CONTAINS_ALL
, e JSON_CONTAINS_ANY
.
Filtra todas as entidades que têm
["blue", "brown", "grey"]
como o conjunto de cores de referência.# 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" # ] # ] # } # } # ]
// 5. Advanced search within a JSON field searchReq = SearchReq.builder() .collectionName("test_collection") .data(query_vectors) .filter("JSON_CONTAINS(color[\"ref\"], [\"purple\", \"pink\", \"orange\"])") .outputFields(Arrays.asList("id", "color")) .topK(3) .build(); searchResp = client.search(searchReq); searchResults = searchResp.getSearchResults(); for (List<SearchResp.SearchResult> results : searchResults) { System.out.println("TopK results:"); for (SearchResp.SearchResult result : results) { System.out.println(result); } } // Output: // SearchResp.SearchResult(entity={color={"label":"pink","tag":2963,"coord":[15,33,30],"ref":[["green","white","white"],["purple","pink","orange"],["yellow","black","pink"]]}, id=273}, score=0.46558747, id=273) // SearchResp.SearchResult(entity={color={"label":"pink","tag":4027,"coord":[32,34,19],"ref":[["red","white","blue"],["white","pink","yellow"],["purple","pink","orange"]]}, id=344}, score=0.2637315, id=344) // SearchResp.SearchResult(entity={color={"label":"black","tag":1603,"coord":[33,12,23],"ref":[["pink","brown","black"],["black","purple","black"],["purple","pink","orange"]]}, id=205}, score=0.26133868, id=205)
// 5. Advanced search within a JSON field res = await client.search({ collection_name: "test_collection", data: query_vectors, filter: 'JSON_CONTAINS(color["ref"], ["blue", "brown", "grey"])', output_fields: ["color", "id"], limit: 3 }) console.log(JSON.stringify(res.results, null, 4)) // 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" // ] // ] // } // } // ] //
Filtra entidades que têm o coordenador de
[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" # ] # ] # } # } # ]
searchReq = SearchReq.builder() .collectionName("test_collection") .data(query_vectors) .filter("JSON_CONTAINS_ALL(color[\"coord\"], [4, 5])") .outputFields(Arrays.asList("id", "color")) .topK(3) .build(); searchResp = client.search(searchReq); searchResults = searchResp.getSearchResults(); for (List<SearchResp.SearchResult> results : searchResults) { System.out.println("TopK results:"); for (SearchResp.SearchResult result : results) { System.out.println(result); } } // Output: // SearchResp.SearchResult(entity={color={"label":"green","tag":9899,"coord":[5,4,25],"ref":[["purple","black","yellow"],["orange","green","purple"],["red","purple","pink"]]}, id=708}, score=0.56576324, id=708) // SearchResp.SearchResult(entity={color={"label":"red","tag":2176,"coord":[4,5,23],"ref":[["red","black","green"],["brown","orange","brown"],["brown","orange","yellow"]]}, id=981}, score=0.5656834, id=981) // SearchResp.SearchResult(entity={color={"label":"pink","tag":3085,"coord":[5,3,4],"ref":[["yellow","orange","green"],["black","pink","red"],["orange","blue","blue"]]}, id=221}, score=0.3708634, id=221)
res = await client.search({ collection_name: "test_collection", data: query_vectors, filter: 'JSON_CONTAINS_ALL(color["coord"], [4, 5])', output_fields: ["color", "id"], limit: 3 }) console.log(JSON.stringify(res.results, null, 4)) // Output // // [ // { // "score": 1.8944344520568848, // "id": "792", // "color": { // "label": "purple", // "tag": 8161, // "coord": [ // 4, // 38, // 5 // ], // "ref": [ // [ // "red", // "white", // "grey" // ] // ] // } // }, // { // "score": 1.2801706790924072, // "id": "489", // "color": { // "label": "red", // "tag": 4358, // "coord": [ // 5, // 4, // 1 // ], // "ref": [ // [ // "blue", // "orange", // "orange" // ] // ] // } // }, // { // "score": 1.2097992897033691, // "id": "656", // "color": { // "label": "red", // "tag": 7856, // "coord": [ // 5, // 20, // 4 // ], // "ref": [ // [ // "black", // "orange", // "white" // ] // ] // } // } // ] //
Filtra entidades que têm o coordenador que contém
4
ou5
.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" # ] # ] # } # } # ]
searchReq = SearchReq.builder() .collectionName("test_collection") .data(query_vectors) .filter("JSON_CONTAINS_ANY(color[\"coord\"], [4, 5])") .outputFields(Arrays.asList("id", "color")) .topK(3) .build(); searchResp = client.search(searchReq); searchResults = searchResp.getSearchResults(); for (List<SearchResp.SearchResult> results : searchResults) { System.out.println("TopK results:"); for (SearchResp.SearchResult result : results) { System.out.println(result); } } // Output: // SearchResp.SearchResult(entity={color={"label":"brown","tag":8414,"coord":[3,4,15],"ref":[["blue","green","pink"],["red","orange","pink"],["yellow","pink","green"]]}, id=11}, score=1.18235, id=11) // SearchResp.SearchResult(entity={color={"label":"yellow","tag":2846,"coord":[20,4,15],"ref":[["white","black","purple"],["green","black","yellow"],["red","purple","brown"]]}, id=589}, score=1.1414992, id=589) // SearchResp.SearchResult(entity={color={"label":"pink","tag":6744,"coord":[25,33,5],"ref":[["orange","purple","white"],["white","pink","brown"],["red","pink","red"]]}, id=567}, score=1.1087029, id=567)
res = await client.search({ collection_name: "test_collection", data: query_vectors, filter: 'JSON_CONTAINS_ANY(color["coord"], [4, 5])', output_fields: ["color", "id"], limit: 3 }) console.log(JSON.stringify(res.results, null, 4)) // Output // // [ // { // "score": 1.9083369970321655, // "id": "453", // "color": { // "label": "brown", // "tag": 8788, // "coord": [ // 21, // 18, // 5 // ], // "ref": [ // [ // "pink", // "black", // "brown" // ] // ] // } // }, // { // "score": 1.8944344520568848, // "id": "792", // "color": { // "label": "purple", // "tag": 8161, // "coord": [ // 4, // 38, // 5 // ], // "ref": [ // [ // "red", // "white", // "grey" // ] // ] // } // }, // { // "score": 1.8615753650665283, // "id": "272", // "color": { // "label": "grey", // "tag": 3400, // "coord": [ // 5, // 1, // 32 // ], // "ref": [ // [ // "purple", // "green", // "white" // ] // ] // } // } // ] //
Referência sobre filtros JSON
Ao trabalhar com campos JSON, pode utilizar os campos JSON como filtros ou algumas das suas chaves específicas.
notas
- O Milvus armazena os valores das cadeias de caracteres no campo JSON tal como estão, sem efetuar a conversão ou a fuga semântica.
Por exemplo, 'a"b'
, "a'b"
, 'a\\\\'b'
, e "a\\\\"b"
serão guardados tal como estão, enquanto 'a'b'
e "a"b"
serão tratados como valores inválidos.
Para criar expressões de filtro utilizando um campo JSON, pode utilizar as chaves dentro do campo.
Se o valor de uma chave for um inteiro ou um float, pode compará-lo com outra chave de inteiro ou float ou com um campo INT32/64 ou FLOAT32/64.
Se o valor de uma chave for uma cadeia de caracteres, só pode compará-lo com outra chave de cadeia de caracteres ou com um campo VARCHAR.
Operadores básicos em campos JSON
A tabela seguinte pressupõe que o valor de um campo JSON denominado json_key
tem uma chave denominada A
. Utilize-a como referência quando construir expressões booleanas utilizando chaves de campo JSON.
Operador | Exemplos | Observações |
---|---|---|
< | 'json_field["A"] < 3' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for menor que 3 . |
> | 'json_field["A"] > 1' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for maior que 1 . |
== | 'json_field["A"] == 1' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for igual a 1 . |
!= | 'json_field["A"][0]' != "abc"' | Esta expressão é avaliada como verdadeira se - json_field não tiver uma chave chamada A .- json_field tem uma chave chamada A mas json_field["A"] não é uma matriz.- json_field["A"] é uma matriz vazia.- json_field["A"] é uma matriz, mas o primeiro elemento não é abc . |
<= | 'json_field["A"] <= 5' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for menor ou igual a 5 . |
>= | 'json_field["A"] >= 1' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for maior ou igual a 1 . |
não | 'not json_field["A"] == 1' | Esta expressão é avaliada como verdadeira se - json_field não tiver uma chave chamada A .- json_field["A"] não for igual a 1 . |
in | 'json_field["A"] in [1, 2, 3]' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for 1 , 2 , ou 3 . |
and (&&) | 'json_field["A"] > 1 && json_field["A"] < 3' | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for maior que 1 e menor que 3 . |
or (||) | ‘json_field[“A”] > 1 || json_field[“A”] < 3’ | Esta expressão é avaliada como verdadeira se o valor de json_field["A"] for maior que 1 ou menor que 3 . |
existe | 'exists json_field["A"]' | Esta expressão é avaliada como verdadeira se json_field tiver uma chave chamada A . |
Operadores avançados
Os seguintes operadores são específicos dos campos JSON:
json_contains(identifier, jsonExpr)
Este operador filtra entidades cujo identificador contém a expressão JSON especificada.
Exemplo 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".)
Exemplo 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)
Este operador filtra entidades cujo identificador contém todos os membros da expressão JSON.
Exemplo:
{"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)
Este operador filtra entidades cujo identificador contém qualquer membro da expressão JSON.
Exemplo:
{"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.)