Vector and keyword search
Beyond selecting the right search type, you can fine-tune search behavior to improve result quality.
Combining searches with filters
Filters can be combined with searches to narrow results. Note that in Weaviate, filters are applied alongside search, meaning that all matching objects will be returned.
Weaviate allows multiple filters to be combined, as well as metadata-based filtering.
This example shows how to use filters, so that a search for articles about "artificial intelligence" is limited to those that:
- contain the word
"automotive", and - were created after May 1, 2025.
from weaviate.classes.query import Filter
from datetime import datetime
articles = client.collections.use("Articles")
filters = (
Filter.by_property("title").like("*automotive*") &
Filter.by_creation_time().greater_or_equal(datetime(2025, 5, 1))
)
articles.query.near_text(
query="artificial intelligence",
limit=10,
filters=filters
)
By default, metadata of timestamps, null states, and property lengths are not indexed. Enable them first in the inverted index configuration before using them in filters.
Vector search strategies
You've already learned how selecting the right embedding model can impact search quality. But there are many other ways to optimize vector search.
Property selection for vectorization
By default, all eligible properties are vectorized. But not all properties should contribute to the semantic meaning.
Metadata fields like IDs, timestamps, or internal codes can add noise. In other cases, you may only want to vectorize certain properties to support your search strategy.
So, carefully consider which source properties to include in your vector.
from weaviate.classes.config import Property, DataType, Configure, Tokenization
client.collections.create(
name="Products",
properties=[
Property(name="name", data_type=DataType.TEXT),
Property(name="description", data_type=DataType.TEXT),
Property(name="category", data_type=DataType.TEXT_ARRAY),
Property(
name="product_id",
data_type=DataType.TEXT,
skip_vectorization=True, # Exclude from vector
tokenization=Tokenization.FIELD
),
Property(
name="product_image",
data_type=DataType.BLOB
)
],
# Vector includes only: name + description + category
# Result: Cleaner semantic representation
vector_config=Configure.Vectors.text2vec_weaviate(
source_properties=["name", "description", "category"]
)
)
Skip vectorization for metadata, such as:
- IDs and internal codes
- Timestamps and dates
- Status flags (active/inactive)
Consider including:
- Content descriptions and titles
- Categories and tags (if semantically meaningful)
- Additional context for embedding
Multiple vectors per object
Each object can have multiple independent vectors, each with its own index.
As a result, each vector can be optimized for a different use case.
Example:
- A product with a
textvector for semantic search, and animagevector for image similarity.
from weaviate.classes.config import Property, DataType, Configure, Tokenization
client.collections.create(
name="Products",
properties=[
Property(name="name", data_type=DataType.TEXT),
Property(name="description", data_type=DataType.TEXT),
Property(name="category", data_type=DataType.TEXT_ARRAY),
Property(
name="product_id",
data_type=DataType.TEXT,
skip_vectorization=True, # Exclude from vector
tokenization=Tokenization.FIELD
),
Property(
name="product_image",
data_type=DataType.BLOB
)
],
# Create two vectors per object: One for text, one for image
vector_config=[
Configure.Vectors.text2vec_weaviate(
name="text",
source_properties=["name", "description", "category"]
),
Configure.Vectors.multi2vec_cohere(
name="image",
image_fields=["product_image"],
model="embed-v4.0"
),
]
)
Multi-target vector search
Multi-target vector search allows you to search on multiple vectors at once.
This can blend similarities against multiple vectors, and provide a robust retrieval solution for more complex use cases, or where a user behavior may be unpredictable.
Here is an example of how to perform multi-target vector search.
from weaviate.classes.query import TargetVectors
products = client.collections.use("Products")
response = products.query.near_text(
query="red minimalist wireless headphones",
target_vectors=TargetVectors.minimum(["text", "image"]), # How to weight the vector distances
limit=10
)
Note that the distance from each vector can be weighted according to your use case. Use the TargetVectors class to weight the vectors, such as using a .minimum distance, or a .average distance, or even using a set of .manual_weights.
Now let's explore keyword and hybrid search strategies, as well as re-rankers in the next lesson.