Skip to main content

Index StructArray Fields

Public Preview

Create indexes on StructArray subfields before you run vector search or accelerate scalar filtering. For a StructArray field, the index target is a subfield path, such as chunks[emb_list_vector], chunks[emb], or chunks[section].

This page uses the tech_articles collection from Create a StructArray Field. The chunks StructArray field contains scalar subfields for filtering and vector subfields for search.

Before you begin

Make sure the collection schema already contains the chunks StructArray field and data has been inserted.

Subfield pathTypeIndex purpose
chunks[emb_list_vector]FLOAT_VECTOREmbeddingList search with MAX_SIM* metrics.
chunks[emb]FLOAT_VECTORElement-level search with regular vector metrics.
chunks[section]VARCHARCategorical filtering.
chunks[quality_score]FLOATNumeric filtering and range-style predicates.
chunks[has_code]BOOLBoolean filtering.
📘Notes

A vector field or vector subfield accepts only one index. If you need both EmbeddingList search and element-level search, create two separate vector subfields and index them separately. In this page, chunks[emb_list_vector] is indexed for EmbeddingList search, and chunks[emb] is indexed for element-level search.

Choose indexes

Use the search mode to choose the vector metric family.

Search or filter goalTarget pathWhat to choose
EmbeddingList searchchunks[emb_list_vector]A MAX_SIM* metric family.
Element-level vector searchchunks[emb]A regular vector metric family, such as COSINE, IP, or L2.
Filter by string or categorychunks[section]A scalar index supported by your target.
Filter by numeric rangechunks[quality_score], chunks[page]A scalar index supported by your target.
Filter by boolean valuechunks[has_code]A scalar index supported by your target.

EmbeddingList search treats the vectors in a StructArray vector subfield as an embedding list and returns entity-level results. Element-level search searches each Struct element independently and can return the matched element offset.

Create vector indexes

The following example creates two vector indexes. The first index uses a MAX_SIM* metric for EmbeddingList search. The second index uses a regular vector metric for element-level search.

Use AUTOINDEX for StructArray vector subfields.

python
index_params = client.prepare_index_params()

index_params.add_index(
field_name="chunks[emb_list_vector]",
index_name="chunks_emb_list_auto",
index_type="AUTOINDEX",
metric_type="MAX_SIM_COSINE",
)

index_params.add_index(
field_name="chunks[emb]",
index_name="chunks_emb_auto",
index_type="AUTOINDEX",
metric_type="COSINE",
)

client.create_index(
collection_name="tech_articles",
index_params=index_params,
)
🚧Warning

Do not create a MAX_SIM* index and a regular vector-metric index on the same vector subfield. If both search modes are required, write vectors to two separate vector subfields and create one index on each subfield.

Create scalar indexes

Create scalar indexes on StructArray scalar subfields when you use them in filters. Use the same structArray[subfield] path syntax. Applicable index types are INVERTED, BITMAP, and STL_SORT.

Use AUTOINDEX for StructArray scalar subfields.

python
index_params = client.prepare_index_params()

index_params.add_index(
field_name="chunks[section]",
index_name="chunks_section_auto",
index_type="AUTOINDEX",
)

index_params.add_index(
field_name="chunks[has_code]",
index_name="chunks_has_code_auto",
index_type="AUTOINDEX",
)

index_params.add_index(
field_name="chunks[quality_score]",
index_name="chunks_quality_score_auto",
index_type="AUTOINDEX",
)

index_params.add_index(
field_name="chunks[page]",
index_name="chunks_page_auto",
index_type="AUTOINDEX",
)

client.create_index(
collection_name="tech_articles",
index_params=index_params,
)

Scalar indexes are optional but useful when StructArray scalar subfields appear frequently in filters, such as element_filter(chunks, $[quality_score] > 0.9) or MATCH_ANY(chunks, $[section] == "index").

Applicable metric types

Use the following table to understand the metric types applicable to a StructArray field.

Metric TypeDescription
MAX_SIM_COSINE (MAX_SIM)Measures the similarity between 2 vectors based on Cosine, and then calculates the similarity between 2 vector lists using MaxSim.
MAX_SIM_L2Measures the similarity between 2 vectors based on L2, and then calculates the similarity between 2 vector lists using MaxSim.
MAX_SIM_IPMeasures the similarity between 2 vectors based on IP, and then calculates the similarity between 2 vector lists using MaxSim.
MAX_SIM_HAMMINGMeasures the similarity between 2 vectors based on Hamming, and then calculates the similarity between 2 vector lists using MaxSim.
MAX_SIM_JACCARDMeasures the similarity between 2 vectors based on Jaccard, and then calculates the similarity between 2 vector lists using MaxSim.

The following formula applies when you calculate the distance between the query embedding list and a vector subfield in a StructArray field.

Distance({q},{v})=Σ{i=1}{n}(Max{j=1}{m}Distance(qi,vj))Distance(\{q\}, \{v\})=\Sigma_\{i=1\}^\{n\}(Max_\{j=1\}^\{m\}Distance(q_i,v_j))

In the above formula, qqrefers to an embedding list of nnelements, while vv refers to a StrctArray subfield containing mmelements.

Index metric compatibility

Use the following tables to choose an index type and metric type for a StructArray vector subfield. Start from the target, then choose the metric family by search mode.

Use AUTOINDEX for StructArray vector subfields. Choose the metric type from the metric family required by the search mode.

Search modeVector subfield data typeIndex typeMetric type
EmbeddingList searchFLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR, INT8_VECTORAUTOINDEXMAX_SIM, MAX_SIM_COSINE, MAX_SIM_IP, MAX_SIM_L2
EmbeddingList searchBINARY_VECTORAUTOINDEXMAX_SIM_HAMMING, MAX_SIM_JACCARD
Element-level searchFLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR, INT8_VECTORAUTOINDEXL2, IP, COSINE
Element-level searchBINARY_VECTORAUTOINDEXHAMMING, JACCARD

For version-specific support and other limits, see StructArray Limits.

Verify indexes

After creating indexes, describe the collection or list indexes to confirm that the expected subfield paths are indexed.

python
indexes = client.list_indexes(
collection_name="tech_articles",
)

print(indexes)

You can also describe a specific index if your SDK version exposes index-description APIs.

python
index = client.describe_index(
collection_name="tech_articles",
index_name="chunks_emb_cosine",
)

print(index)

Index rules

RuleExplanation
Use path syntax for subfield indexes.Index chunks[emb], not emb or chunks.emb.
One vector subfield accepts one index.Use separate vector subfields if you need different metric families.
Use MAX_SIM* metrics for EmbeddingList search.EmbeddingList query data requires an index built with a MAX_SIM* metric.
Use regular vector metrics for element-level search.Element-level search uses regular vector query data and metrics such as COSINE, IP, or L2.
Index scalar subfields that appear in filters.Use scalar index types supported by your target.
Keep vector-field limits in mind.The total number of vector fields and vector subfields is limited. See StructArray Limits before adding many vector subfields.

Common mistakes

  • Creating an index on chunks.emb instead of chunks[emb].

  • Creating only a MAX_SIM* index and then trying to run element-level search on the same subfield.

  • Creating only a regular vector index and then trying to run EmbeddingList search on the same subfield.

  • Reusing one vector subfield for both MAX_SIM* and regular vector metrics.

  • Forgetting scalar indexes for heavily used StructArray filters.

  • Indexing a StructArray subfield that does not exist in the Struct schema.

Next steps

  1. To run entity-level EmbeddingList search or element-level vector search, read Basic Vector Search with StructArray.

  2. To filter StructArray scalar subfields during search, read Filtered Search with StructArray.

  3. To review index and metric limits, read StructArray Limits.

Ctrl I