Menggunakan Bidang Array

Panduan ini menjelaskan cara menggunakan bidang larik, seperti menyisipkan nilai larik, membuat indeks pada bidang vektor dan larik, serta mencari dan melakukan kueri dalam bidang larik dengan operator dasar dan lanjutan.

Prasyarat

Pastikan Anda memiliki hal-hal berikut ini:

  • Milvus telah terinstal dan berjalan. Untuk informasi tentang cara menginstal Milvus, lihat Menginstal Milvus.
  • Salah satu SDK Milvus terinstal di lingkungan Anda. Untuk informasi lebih lanjut, lihat Menginstal SDK.

Mempersiapkan data dengan bidang array

Milvus mendukung larik sebagai salah satu tipe data field. Larik dalam koleksi Milvus harus selalu memiliki elemen dengan tipe data yang sama, dan tipe data untuk elemen larik dapat berupa salah satu tipe data yang didukung di Milvus. Untuk daftar tipe data yang didukung, lihat Tipe data yang didukung.

Cuplikan kode berikut ini menghasilkan kumpulan data acak yang berisi bidang larik bernama color_coord, dengan semua elemen tipe data interger.

import random

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(random.randint(3, 5)) ]
    data.append({
        "id": i,
        "vector": [ random.uniform(-1, 1) for _ in range(5) ],
        "color": current_color,
        "color_tag": current_tag,
        "color_coord": current_coord,
    })

print(data[0])
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.util.*;

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;

    // Generate an random-sized array
    int capacity = rand.nextInt(5) + 1;
    List<Integer> current_coord = new ArrayList<>();
    for (int j=0; j<capacity; j++) {
        current_coord.add(rand.nextInt(40));
    }

    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())));
    row.addProperty("color", current_color);
    row.addProperty("color_tag", current_tag);
    row.add("color_coord", gson.toJsonTree(current_coord));
    data.add(row);
}

System.out.println(data.get(0));
const colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"];
let 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(Math.floor(Math.random() * 5 + 1)).fill(0).map(() => Math.floor(Math.random() * 40));

    data.push({
        id: i,
        vector: Array(5).fill(0).map(() => Math.random()),
        color: current_color,
        color_tag: current_tag,
        color_coord: current_coord,
    });
}

console.log(data[0]);

Cuplikan kode ini menyiapkan daftar warna acak dan menghasilkan kumpulan data yang berisi 1.000 entitas. Setiap entitas memiliki ID, vektor lima angka floating-point, warna, tag warna, dan bidang larik color_coord yang berisi antara 3 hingga 5 nilai integer. Data sampel dicetak untuk memverifikasi strukturnya.

Struktur keluaran:

{
    id: 0,
    vector: [
        0.0338537420906162,
        0.6844108238358322,
        0.28410588909961754,
        0.09752595400212116,
        0.22671013058761114
    ],
    color: 'orange',
    color_tag: 5677,
    color_coord: [ 3, 0, 18, 29 ]
}

Menyiapkan MilvusClient

Untuk berinteraksi dengan Milvus, siapkan klien Milvus dengan menentukan alamat server.

from pymilvus import MilvusClient, DataType

SERVER_ADDR = "http://localhost:19530"

client = MilvusClient(uri=SERVER_ADDR)
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.index.request.CreateIndexReq;
import io.milvus.v2.service.vector.request.*;
import io.milvus.v2.service.vector.response.*;

String SERVER_ADDR = "http://localhost:19530";

// 1. Connect to Milvus server
ConnectConfig connectConfig = ConnectConfig.builder()
    .uri(SERVER_ADDR)
    .build();

MilvusClientV2 client = new MilvusClientV2(connectConfig);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

// Connect to Milvus server
const address = "http://localhost:19530";

const milvusClient = new MilvusClient({address: address});

Membuat koleksi dengan bidang array

Menentukan skema koleksi

Skema mendefinisikan struktur koleksi, termasuk bidang dan tipe datanya. Contoh di bawah ini mendefinisikan skema koleksi yang cocok dengan contoh data yang dibuat di bagian sebelumnya.

Untuk mengonfigurasi bidang array dalam koleksi:

  1. Tetapkan datatype: Konfigurasikan sebagai DataType.ARRAY.
  2. Tentukan element_type: Pilih tipe data untuk elemen dalam larik. Elemen dalam bidang larik harus memiliki tipe data yang sama. Dalam contoh ini, element_type diatur ke DataType.INT64.
  3. Tentukan max_capacity: Tetapkan parameter ini untuk menentukan jumlah maksimum elemen yang dapat ditampung oleh bidang array.
  1. Tentukan dataType: Konfigurasikan sebagai DataType.Array.
  2. Tentukan elementType: Pilih tipe data untuk elemen dalam larik. Elemen dalam bidang larik harus memiliki tipe data yang sama. Dalam contoh ini, elementType diatur ke DataType.Int64.
  3. Tentukan maxCapacity: Tetapkan parameter ini untuk menentukan jumlah maksimum elemen yang dapat ditampung oleh bidang array.
  1. Tentukan data_type: Konfigurasikan sebagai DataType.Array.
  2. Tentukan element_type: Pilih tipe data untuk elemen dalam larik. Elemen dalam bidang larik harus memiliki tipe data yang sama. Dalam contoh ini, element_type diatur ke DataType.Int64.
  3. Tentukan max_capacity: Tetapkan parameter ini untuk menentukan jumlah maksimum elemen yang dapat ditampung oleh bidang array.

Contoh kode di bawah ini mendefinisikan skema koleksi dengan bidang array color_coord, dengan maksimum 5 elemen dan setiap elemen bertipe data integer.

schema = client.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.VARCHAR, max_length=512)
schema.add_field(field_name="color_tag", datatype=DataType.INT64)
schema.add_field(field_name="color_coord", datatype=DataType.ARRAY, element_type=DataType.INT64, max_capacity=5)
// Create schema
CreateCollectionReq.CollectionSchema schema = client.createSchema();

// 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.VarChar)
        .maxLength(512)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("color_tag")
        .dataType(DataType.Int64)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("color_coord")
        .dataType(DataType.Array)
        .elementType(DataType.Int64)
        .maxCapacity(5)
        .build());
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.VarChar,
        max_length: 512
    },
    {
        name: "color_tag",
        data_type: DataType.Int64,
    },
    {
        name: "color_coord",
        data_type: DataType.Array,
        element_type: DataType.Int64,
        max_capacity: 5
    }
];

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat create_schema dan add_field.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createSchema dan addField.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createCollection.

Membuat koleksi

Kemudian, buat koleksi menggunakan skema yang telah didefinisikan.

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

# Output:
# ['test_collection']
CreateCollectionReq customizedSetupReq = CreateCollectionReq.builder()
    .collectionName("test_collection")
    .collectionSchema(schema)
    .build();

client.createCollection(customizedSetupReq);
await client.createCollection({
    collection_name: "test_collection",
    fields: fields
});

const res = await client.listCollections({collection_name: "test_collection"});

console.log("Existing collections: " + res.collection_names);

// Output:
// Existing collections: test_collection

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat create_collection dan list_collections.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createCollection.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createCollection dan listCollections.

Membuat indeks

Indeks meningkatkan kinerja operasi pencarian dan kueri. Di Milvus, Anda dapat membuat indeks pada bidang vektor dan bidang skalar. Pada contoh ini, kita akan membuat indeks IVF_FLAT pada bidang vektor vector dan indeks INVERTED pada bidang larik color_coord. Untuk informasi lebih lanjut tentang indeks, lihat Bidang Vektor Indeks dan Bidang Skalar Indeks.

Bidang vektor indeks

Membuat indeks pada bidang vektor dapat meningkatkan kinerja pencarian kemiripan vektor, yang diperlukan untuk setiap operasi pencarian.

Contoh di bawah ini membuat indeks bertipe IVF_FLAT pada bidang vektor vector.

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="vector",
    metric_type="COSINE",
    index_type="IVF_FLAT",
    index_name="vector_index",
    params={"nlist": 128}
)

client.create_index(collection_name="test_collection", index_params=index_params)
client.describe_index(collection_name="test_collection", index_name="vector_index")

# Output:
# {'nlist': '128',
#  'index_type': 'IVF_FLAT',
#  'metric_type': 'COSINE',
#  'field_name': 'vector',
#  'index_name': 'vector_index'}
IndexParam indexParam = IndexParam.builder()
        .metricType(IndexParam.MetricType.COSINE)
        .indexType(IndexParam.IndexType.IVF_FLAT)
        .fieldName("vector")
        .indexName("vector_index")
        .build();
CreateIndexReq createIndexReq = CreateIndexReq.builder()
        .collectionName("test_collection")
        .indexParams(Collections.singletonList(indexParam))
        .build();
client.createIndex(createIndexReq);
await client.createIndex({
    collection_name: "test_collection",
    field_name: "vector",
    index_type: "IVF_FLAT",
    metric_type: "COSINE",   
    index_name: "vector_index",
    params: { "nlist": 128 }
});

res = await client.describeIndex({
    collection_name: "test_collection",
    index_name: "vector_index"
});

console.log("Vector index description: " + JSON.stringify(res));

// Output:
// Vector index description: {"index_descriptions":[{"params":[{"key":"params","value":"{\"nlist\":128}"},{"key":"index_type","value":"IVF_FLAT"},{"key":"metric_type","value":"COSINE"}],"index_name":"vector_index","indexID":"451543183233666062","field_name":"vector","indexed_rows":"0","total_rows":"0","state":"Finished","index_state_fail_reason":"","pending_index_rows":"0"}],"status":{"extra_info":{},"error_code":"Success","reason":"","code":0,"retriable":false,"detail":""}}

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat prepare_index_params, create_index, dan describe_index.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat IndexParam dan createIndex.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createIndex, dan describeIndex.

Bidang larik indeks

Membuat indeks pada bidang skalar dapat meningkatkan performa pengambilan kueri pada bidang tersebut, yang bersifat opsional namun disarankan untuk kumpulan data yang besar.

Dalam contoh ini, kita akan membuat indeks terbalik pada bidang larik color_coord. Hal ini akan memungkinkan kita untuk mempercepat pemfilteran berdasarkan bidang ini. Indeks terbalik menunjukkan kinerja keseluruhan yang sangat baik, secara signifikan mengungguli pemfilteran brute force menggunakan data mentah ketika data tidak sering diambil, dan mempertahankan kinerja yang sebanding dengan operasi pengambilan yang sering. Untuk informasi lebih lanjut tentang indeks terbalik, lihat Indeks Skalar.

index_params = client.prepare_index_params()

index_params.add_index(
    field_name="color_coord",
    index_type="INVERTED",
    index_name="inverted_index"
)

client.create_index(collection_name="test_collection", index_params=index_params)
client.describe_index(collection_name="test_collection", index_name="inverted_index")

# Output:
# {'index_type': 'INVERTED',
#  'field_name': 'color_coord',
#  'index_name': 'inverted_index'}
indexParam = IndexParam.builder()
        .indexType(IndexParam.IndexType.INVERTED)
        .fieldName("color_coord")
        .indexName("inverted_index")
        .build();
createIndexReq = CreateIndexReq.builder()
        .collectionName("test_collection")
        .indexParams(Collections.singletonList(indexParam))
        .build();
client.createIndex(createIndexReq);
await client.createIndex({
    collection_name: "test_collection",
    field_name: "color_coord",
    index_type: "INVERTED",
    index_name: "inverted_index"
});

res = await client.describeIndex({
    collection_name: "test_collection",
    index_name: "inverted_index"
});

console.log("Array index description: " + JSON.stringify(res));

// Output:
// Array index description: {"index_descriptions":[{"params":[{"key":"index_type","value":"INVERTED"}],"index_name":"inverted_index","indexID":"451543183233667243","field_name":"color_coord","indexed_rows":"0","total_rows":"0","state":"Finished","index_state_fail_reason":"","pending_index_rows":"0"}],"status":{"extra_info":{},"error_code":"Success","reason":"","code":0,"retriable":false,"detail":""}}

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat prepare_index_params, create_index, dan describe_index.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat IndexParam dan createIndex.

Untuk informasi lebih lanjut mengenai metode dan parameter, lihat createIndex, dan describeIndex.

Memasukkan data

Setelah koleksi dan indeks dibuat, kita dapat menyisipkan data ke dalam koleksi. Langkah ini menyisipkan 1.000 entitas ke dalam test_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, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999], 'cost': 0}
InsertReq insertReq = InsertReq.builder()
    .collectionName("test_collection")
    .data(data)
    .build();

InsertResp insertResp = client.insert(insertReq);
res = await client.insert({
    collection_name: "test_collection",
    data: data
});

console.log(`Inserted ${res.insert_cnt} entities`);

// Output:
// Inserted 1000 entities

Memuat koleksi

Setelah memasukkan data, kita perlu memuat koleksi agar tersedia untuk operasi pencarian dan kueri.

client.load_collection('test_collection')
LoadCollectionReq loadCollectionReq = LoadCollectionReq.builder()
        .collectionName("test_collection")
        .build();
client.loadCollection(loadCollectionReq);
await client.loadCollection({
    collection_name: "test_collection"
});

res = await client.getLoadState({
    collection_name: "test_collection"
});

console.log("Collection load state: " + res.state);

// Output:
// Collection load state: LoadStateLoaded

Pemfilteran skalar dasar

Setelah semua data Anda ditambahkan, Anda dapat melakukan pencarian dan kueri menggunakan elemen dalam bidang larik dengan cara yang sama seperti yang Anda lakukan dengan bidang skalar standar.

Untuk informasi lebih lanjut tentang parameter, lihat search() dalam referensi SDK.

Untuk informasi lebih lanjut tentang parameter, lihat search() dalam referensi SDK.

Untuk informasi lebih lanjut tentang parameter, lihat search() dalam referensi SDK.

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

res = client.search(
    collection_name="test_collection",
    data=query_vectors,
    filter="color_coord[0] < 10",
    search_params={
        "metric_type": "COSINE",
        "params": {"nprobe": 16}
    },
    output_fields=["id", "color", "color_tag", "color_coord"],
    limit=3
)

print(res)

# Output:
# data: ["[{'id': 918, 'distance': 0.974249541759491, 'entity': {'color_coord': [4, 34, 9, 18, 29], 'id': 918, 'color': 'purple', 'color_tag': 2940}}, {'id': 822, 'distance': 0.9177230000495911, 'entity': {'color_coord': [7, 36, 32], 'id': 822, 'color': 'red', 'color_tag': 8519}}, {'id': 981, 'distance': 0.9116519689559937, 'entity': {'color_coord': [7, 16, 40, 32, 32], 'id': 981, 'color': 'pink', 'color_tag': 2992}}]"] , extra_info: {'cost': 0}
// 4. Basic search with an Array field
QueryReq queryReq = QueryReq.builder()
        .collectionName("test_collection")
        .filter("color_coord[0] in [7, 8, 9]")
        .outputFields(Arrays.asList("id", "color", "color_tag", "color_coord"))
        .limit(3L)
        .build();

QueryResp queryResp = client.query(queryReq);

System.out.println(queryResp.getQueryResults());

// Output:
// [
//  QueryResp.QueryResult(entity={color=black, color_tag=6107, id=8, color_coord=[8, 19, 31, 10]}), 
//  QueryResp.QueryResult(entity={color=blue, color_tag=3252, id=11, color_coord=[7, 16, 1]}),
//  QueryResp.QueryResult(entity={color=blue, color_tag=3069, id=16, color_coord=[9, 16, 19]})
// ]
const query_vectors = [Array(5).fill(0).map(() => Math.random())];

res = await client.search({
    collection_name: "test_collection",
    data: query_vectors,
    filter: "color_coord[0] < 10",
    output_fields: ["id", "color", "color_tag", "color_coord"],
    limit: 3,
    metric_type: "COSINE"
});

console.log("Search result: " + JSON.stringify(res));

// Output:
// Search result: [
//     {
//         "score": 0.9969238042831421,
//         "id": "212",
//         "color": "green",
//         "color_tag": "5603",
//         "color_coord": [
//             "9",
//             "14",
//             "22",
//             "4",
//             "35"
//         ]
//     },
//     {
//         "score": 0.9952742457389832,
//         "id": "339",
//         "color": "yellow",
//         "color_tag": "8867",
//         "color_coord": [
//             "8",
//             "0",
//             "6",
//             "19",
//             "23"
//         ]
//     },
//     {
//         "score": 0.9944050312042236,
//         "id": "24",
//         "color": "red",
//         "color_tag": "7686",
//         "color_coord": [
//             "6",
//             "17",
//             "6",
//             "32"
//         ]
//     }
// ]

Pemfilteran tingkat lanjut

Seperti apa yang kita miliki di bidang JSON, Milvus juga menyediakan operator pemfilteran tingkat lanjut untuk array, yaitu ARRAY_CONTAINS, ARRAY_CONTAINS_ALL, ARRAY_CONTAINS_ANY, dan ARRAY_LENGTH. Untuk informasi lebih lanjut mengenai operator, lihat Referensi mengenai filter larik.

  • Memfilter semua entitas yang memiliki 10 dalam nilai color_coord.

    # 5. Advanced query within the array field
    
    res = client.query(
        collection_name="test_collection",
        filter="ARRAY_CONTAINS(color_coord, 10)",
        output_fields=["id", "color", "color_tag", "color_coord"],
        limit=3
    )
    
    print(res)
    
    # Output:
    # data: ["{'id': 2, 'color': 'green', 'color_tag': 3676, 'color_coord': [26, 37, 30, 10]}", "{'id': 28, 'color': 'red', 'color_tag': 4735, 'color_coord': [30, 10, 40, 34]}", "{'id': 32, 'color': 'green', 'color_tag': 8816, 'color_coord': [10, 9, 24, 39]}"] , extra_info: {'cost': 0}
    
    // 5. Advanced query within an Array field
    queryReq = QueryReq.builder()
            .collectionName("test_collection")
            .filter("ARRAY_CONTAINS(color_coord, 10)")
            .outputFields(Arrays.asList("id", "color", "color_tag", "color_coord"))
            .limit(3)
            .build();
    
    queryResp = client.query(queryReq);
    
    System.out.println(queryResp.getQueryResults());
    
    // Output:
    // [
    //    QueryResp.QueryResult(entity={color=black, color_tag=6107, id=8, color_coord=[8, 19, 31, 10]}), 
    //    QueryResp.QueryResult(entity={color=brown, color_tag=7727, id=17, color_coord=[1, 10, 16, 29]}), 
    //    QueryResp.QueryResult(entity={color=orange, color_tag=8128, id=26, color_coord=[10, 16, 3, 3]})
    // ]
    
    // 5. Advanced search within the array field
    res = await client.search({
        collection_name: "test_collection",
        data: query_vectors,
        filter: "ARRAY_CONTAINS(color_coord, 10)",
        output_fields: ["id", "color", "color_tag", "color_coord"],
        limit: 3
    })
    
    console.log(JSON.stringify(res.results, null, 4))
    
    // Output
    // 
    // [
    //     {
    //         "score": 1.7962548732757568,
    //         "id": "696",
    //         "color": "red",
    //         "color_tag": "1798",
    //         "color_coord": [
    //             "33",
    //             "10",
    //             "37"
    //         ]
    //     },
    //     {
    //         "score": 1.7126177549362183,
    //         "id": "770",
    //         "color": "red",
    //         "color_tag": "1962",
    //         "color_coord": [
    //             "21",
    //             "23",
    //             "10"
    //         ]
    //     },
    //     {
    //         "score": 1.6707111597061157,
    //         "id": "981",
    //         "color": "yellow",
    //         "color_tag": "3100",
    //         "color_coord": [
    //             "28",
    //             "39",
    //             "10",
    //             "6"
    //         ]
    //     }
    // ]
    // 
    
  • Memfilter semua entitas yang memiliki 7 dan 8 dalam nilai color_coord.

    res = client.query(
        collection_name="test_collection",
        filter="ARRAY_CONTAINS_ALL(color_coord, [7, 8])",
        output_fields=["id", "color", "color_tag", "color_coord"],
        limit=3
    )
    
    print(res)
    
    # Output:
    # data: ["{'id': 147, 'color': 'brown', 'color_tag': 1287, 'color_coord': [7, 8, 11, 0]}", "{'id': 257, 'color': 'white', 'color_tag': 3641, 'color_coord': [2, 8, 31, 7]}", "{'id': 280, 'color': 'orange', 'color_tag': 1072, 'color_coord': [22, 7, 8]}"] , extra_info: {'cost': 0}
    
    queryReq = QueryReq.builder()
            .collectionName("test_collection")
            .filter("ARRAY_CONTAINS_ALL(color_coord, [7, 8])")
            .outputFields(Arrays.asList("id", "color", "color_tag", "color_coord"))
            .limit(3)
            .build();
    
    queryResp = client.query(queryReq);
    
    System.out.println(queryResp.getQueryResults());
    
    // Output:
    // [
    //  QueryResp.QueryResult(entity={color=blue, color_tag=6939, id=246, color_coord=[1, 8, 27, 7]}), 
    //  QueryResp.QueryResult(entity={color=brown, color_tag=6341, id=673, color_coord=[8, 7, 33, 20, 11]})
    // ]
    
    res = await client.search({
        collection_name: "test_collection",
        data: query_vectors,
        filter: "ARRAY_CONTAINS_ALL(color_coord, [7, 8])",
        output_fields: ["id", "color", "color_tag", "color_coord"],
        limit: 3
    })
    
    console.log(JSON.stringify(res.results, null, 4))
    
    // Output
    // 
    // [
    //     {
    //         "score": 0.8267516493797302,
    //         "id": "913",
    //         "color": "brown",
    //         "color_tag": "8897",
    //         "color_coord": [
    //             "39",
    //             "31",
    //             "8",
    //             "29",
    //             "7"
    //         ]
    //     },
    //     {
    //         "score": 0.6889009475708008,
    //         "id": "826",
    //         "color": "blue",
    //         "color_tag": "4903",
    //         "color_coord": [
    //             "7",
    //             "25",
    //             "5",
    //             "12",
    //             "8"
    //         ]
    //     },
    //     {
    //         "score": 0.5851659774780273,
    //         "id": "167",
    //         "color": "blue",
    //         "color_tag": "1550",
    //         "color_coord": [
    //             "8",
    //             "27",
    //             "7"
    //         ]
    //     }
    // ]
    // 
    
  • Memfilter semua entitas yang memiliki nilai 7, 8, atau 9 pada nilai color_coord.

    res = client.query(
        collection_name="test_collection",
        filter="ARRAY_CONTAINS_ANY(color_coord, [7, 8, 9])",
        output_fields=["id", "color", "color_tag", "color_coord"],
        limit=3
    )
    
    print(res)
    
    # Output:
    # data: ["{'id': 0, 'color': 'white', 'color_tag': 2081, 'color_coord': [16, 7, 35, 5, 25]}", "{'id': 1, 'color': 'purple', 'color_tag': 4669, 'color_coord': [11, 9, 15, 38, 21]}", "{'id': 3, 'color': 'yellow', 'color_tag': 2612, 'color_coord': [0, 12, 22, 7]}"] , extra_info: {'cost': 0}
    
    queryReq = QueryReq.builder()
            .collectionName("test_collection")
            .filter("ARRAY_CONTAINS_ANY(color_coord, [7, 8, 9])")
            .outputFields(Arrays.asList("id", "color", "color_tag", "color_coord"))
            .limit(3)
            .build();
    
    queryResp = client.query(queryReq);
    
    System.out.println(queryResp.getQueryResults());
    
    // Output:
    // [
    //  QueryResp.QueryResult(entity={color=purple, color_tag=3687, id=1, color_coord=[22, 7, 29, 25]}), 
    //  QueryResp.QueryResult(entity={color=black, color_tag=6107, id=8, color_coord=[8, 19, 31, 10]}), 
    //  QueryResp.QueryResult(entity={color=blue, color_tag=3252, id=11, color_coord=[7, 16, 1]})
    // ]
    
    res = await client.search({
        collection_name: "test_collection",
        data: query_vectors,
        filter: "ARRAY_CONTAINS_ANY(color_coord, [7, 8, 9])",
        output_fields: ["id", "color", "color_tag", "color_coord"],
        limit: 3
    })
    
    console.log(JSON.stringify(res.results, null, 4))
    
    // Output
    // 
    // [
    //     {
    //         "score": 2.015894889831543,
    //         "id": "260",
    //         "color": "green",
    //         "color_tag": "5320",
    //         "color_coord": [
    //             "1",
    //             "7",
    //             "33",
    //             "13",
    //             "23"
    //         ]
    //     },
    //     {
    //         "score": 1.783075213432312,
    //         "id": "593",
    //         "color": "orange",
    //         "color_tag": "4079",
    //         "color_coord": [
    //             "8",
    //             "19"
    //         ]
    //     },
    //     {
    //         "score": 1.7713876962661743,
    //         "id": "874",
    //         "color": "blue",
    //         "color_tag": "7029",
    //         "color_coord": [
    //             "14",
    //             "8",
    //             "15"
    //         ]
    //     }
    // ]
    // 
    
  • Menyaring entitas yang memiliki tepat empat elemen.

    res = client.query(
        collection_name="test_collection",
        filter="ARRAY_LENGTH(color_coord) == 4",
        output_fields=["id", "color", "color_tag", "color_coord"],
        limit=3
    )
    
    print(res)
    
    # Output:
    # data: ["{'id': 2, 'color': 'green', 'color_tag': 3676, 'color_coord': [26, 37, 30, 10]}", "{'id': 3, 'color': 'yellow', 'color_tag': 2612, 'color_coord': [0, 12, 22, 7]}", "{'id': 4, 'color': 'green', 'color_tag': 6912, 'color_coord': [4, 5, 19, 28]}"] , extra_info: {'cost': 0}
    
    queryReq = QueryReq.builder()
            .collectionName("test_collection")
            .filter("ARRAY_LENGTH(color_coord) == 4")
            .outputFields(Arrays.asList("id", "color", "color_tag", "color_coord"))
            .limit(3)
            .build();
    
    queryResp = client.query(queryReq);
    
    System.out.println(queryResp.getQueryResults()); 
    
    // Output:
    // [
    //  QueryResp.QueryResult(entity={color=purple, color_tag=3687, id=1, color_coord=[22, 7, 29, 25]}),
    //  QueryResp.QueryResult(entity={color=yellow, color_tag=1990, id=3, color_coord=[26, 20, 15, 26]}),
    //  QueryResp.QueryResult(entity={color=purple, color_tag=3199, id=4, color_coord=[13, 19, 21, 30]})
    // ]
    
    res = await client.search({
    collection_name: "test_collection",
    data: query_vectors,
    filter: "ARRAY_LENGTH(color_coord) == 4",
    output_fields: ["id", "color", "color_tag", "color_coord"],
    limit: 3
    })
    
    console.log(JSON.stringify(res.results, null, 4))
    
    // Output
    // 
    // [
    //     {
    //         "score": 2.0404388904571533,
    //         "id": "439",
    //         "color": "orange",
    //         "color_tag": "7096",
    //         "color_coord": [
    //             "27",
    //             "34",
    //             "26",
    //             "39"
    //         ]
    //     },
    //     {
    //         "score": 1.9059759378433228,
    //         "id": "918",
    //         "color": "purple",
    //         "color_tag": "2903",
    //         "color_coord": [
    //             "28",
    //             "19",
    //             "36",
    //             "35"
    //         ]
    //     },
    //     {
    //         "score": 1.8385567665100098,
    //         "id": "92",
    //         "color": "yellow",
    //         "color_tag": "4693",
    //         "color_coord": [
    //             "1",
    //             "23",
    //             "2",
    //             "3"
    //         ]
    //     }
    // ]
    // 
    

Batas

  • Elemen-elemen dalam bidang ARRAY harus memiliki tipe data yang sama, yang ditentukan oleh element_type. Semua tipe data valid yang tersedia untuk bidang skalar di Milvus dapat digunakan sebagai element_type. Untuk daftar tipe data yang didukung, lihat Tipe data yang didukung.

  • Jumlah elemen dalam bidang ARRAY harus kurang dari atau sama dengan kapasitas maksimum bidang array, yang ditentukan oleh max_capacity.

Referensi tentang filter array

Saat bekerja dengan bidang array, Anda dapat mengapit nilai string dengan tanda petik ganda ("") atau tanda petik tunggal (''). Penting untuk dicatat bahwa Milvus menyimpan nilai string di dalam field array sebagaimana adanya tanpa melakukan semantic escape atau konversi. Sebagai contoh, 'a "b', "a'b", 'a'b', dan "a "b" akan disimpan apa adanya, sedangkan 'a'b' dan "a "b" akan diperlakukan sebagai nilai yang tidak valid.

Asumsikan bahwa dua bidang larik int_array dan var_array telah didefinisikan. Tabel berikut ini menjelaskan ekspresi boolean yang didukung yang dapat Anda gunakan di expr saat mencari dengan bidang array.

OperatorContohKeterangan
<‘int_array[0] < 3’Ekspresi ini bernilai benar jika nilai int_array[0] kurang dari 3.
>‘int_array[0] > 5’Ekspresi ini bernilai benar jika nilai int_array[0] lebih besar dari 5.
==‘int_array[0] == 0’Ekspresi ini bernilai benar jika nilai int_array[0] sama dengan 0.
!=‘var_array[0] != "a"’Ekspresi ini bernilai benar jika nilai var_array[0] tidak sama dengan “a”.
<=‘int_array[0] <= 3’Ekspresi ini bernilai benar jika nilai int_array[0] lebih kecil dari atau sama dengan 3.
>=‘int_array[0] >= 10’Ekspresi ini bernilai benar jika nilai int_array[0] lebih besar dari atau sama dengan 10.
in'var_array[0] in ["str1", “str2”]'Ekspresi ini bernilai benar jika nilai var_array[0] adalah “str1” atau “str2”.
tidak di'int_array[0] not in [1, 2, 3]'Ekspresi ini bernilai benar jika nilai int_array[0] bukan 1, 2, atau 3.
+, -, *, /, %, **‘int_array[0] + 100 > 200’Ekspresi ini bernilai benar jika nilai int_array[0] + 100 lebih besar dari 200.
suka (LIKE)‘var_array[0] like "prefix%"’Ekspresi ini bernilai benar jika nilai var_array[0] diawali dengan “prefix”.
dan (&&)‘var_array[0] like “prefix%” && int_array[0] <= 100’Ekspresi ini bernilai benar jika nilai var_array[0] diawali dengan “prefix”, dan nilai int_array[0] lebih kecil dari atau sama dengan 100.
atau (||)‘var_array[0] like “prefix%” || int_array[0] <= 100’Ekspresi ini bernilai benar jika nilai var_array[0] diawali dengan “prefix”, atau nilai int_array[0] lebih kecil dari atau sama dengan 100.
array_berisi (ARRAY_BERISI)'array_contains(int_array, 100)'Ekspresi ini bernilai benar jika int_array berisi elemen 100.
array_contains_all (ARRAY_CONTAINS_ALL)'array_contains_all(int_array, [1, 2, 3])'Ekspresi ini bernilai benar jika int_array berisi semua elemen 1, 2, dan 3.
array_berisi_apa saja (ARRAY_BERISI_APA SAJA)'array_contains_any(var_array, ["a", "b", “c”])'Ekspresi ini bernilai benar jika var_array berisi elemen apa pun dari “a”, “b”, dan “c”.
panjang_larik (array_length)‘array_length(int_array) == 10’Ekspresi ini bernilai benar jika int_array berisi tepat 10 elemen.