Skip to main content
Weaviate Docs (migrated from docs.weaviate.io) Docs

Search documentation

Type to search this documentation.

On this pageOverview

Multiple target vectors

In a multi-target vector search, Weaviate searches multiple target vector spaces concurrently. These results are combined using a "join strategy" to produce a single set of search results.

There are multiple ways to specify the target vectors and query vectors, such as:

Multi-target vector search is available for near_xxx queries (from v1.26), as well as hybrid queries (from v1.27).

  • minimum (default) Use the minimum of all vector distances.
  • sum Use the sum of the vector distances.
  • average Use the average of the vector distances.
  • manual weights Use the sum of weighted distances, where the weight is provided for each target vector.
  • relative score Use the sum of weighted normalized distances, where the weight is provided for each target vector.

As a minimum, specify the target vector names as an array of named vectors. This will use the default join strategy.

Python
from weaviate.classes.query import MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_text(    query="a wild animal",    limit=2,    target_vector=["jeopardy_questions_vector", "jeopardy_answers_vector"],  # Specify the target vectors    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    return_metadata=MetadataQuery(distance=True)
TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearText('a wild animal', {  limit: 2,  targetVector: ['jeopardy_questions_vector', 'jeopardy_answers_vector'],  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Go
concepts := []string{"a wild animal"}
nearText := client.GraphQL().NearTextArgBuilder().
  WithConcepts(concepts).
  WithTargetVectors("jeopardy_questions_vector", "jeopardy_answers_vector")

ctx := context.Background()

result, err := client.GraphQL().Get().
WithClassName(className).
WithFields(graphql.Field{Name: "question"}, graphql.Field{Name: "answer"}).
WithNearText(nearText).
Do(ctx)
Complete code
Go
package main

import (
  "context"
  "fmt"
  "os"

  "github.com/weaviate/weaviate-go-client/v5/weaviate"
  "github.com/weaviate/weaviate-go-client/v5/weaviate/graphql"
)

func main() {
  cfg := weaviate.Config{
    Host:   "localhost:8080",
    Scheme: "http",
    Headers: map[string]string{
      "X-Openai-Api-Key": os.Getenv("OPENAI_API_KEY"),
    },
  }

  client, err := weaviate.NewClient(cfg)
  if err != nil {
    panic(err)
  }

  className := "JeopardyTiny"
Java
CollectionHandle<Map<String, Object>> collection =    client.collections.use(COLLECTION_NAME);var response = collection.query.nearText(    // In Java, a plain list of target vectors implies an "average" strategy    Target.average("a wild animal", "jeopardy_questions_vector",        "jeopardy_answers_vector"),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : response.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var collection = client.Collections.Use(CollectionName);var response = await collection.Query.NearText(    query =>        query(["a wild animal"])            .TargetVectorsMinimum("jeopardy_questions_vector", "jeopardy_answers_vector"), // Specify the target vectors    limit: 2,    returnMetadata: MetadataOptions.Distance);foreach (var o in response.Objects){    Console.WriteLine(JsonSerializer.Serialize(o.Properties));    Console.WriteLine(o.Metadata.Distance);}

You can specify multiple query vectors in the search query with a nearVector search. This allows use of a different query vector for each corresponding target vector.

Python
from weaviate.classes.query import MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_vector(    # Specify the query vectors for each target vector    near_vector={        "jeopardy_questions_vector": v1,        "jeopardy_answers_vector": v2,    },    limit=2,    target_vector=["jeopardy_questions_vector", "jeopardy_answers_vector"],  # Specify the target vectors    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    return_metadata=MetadataQuery(distance=True)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearVector({  'jeopardy_questions_vector': v1,  'jeopardy_answers_vector': v2}, {  limit: 2,  targetVector: ['jeopardy_questions_vector', 'jeopardy_answers_vector'],  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
var response = collection.query.nearVector(    // Specify the query vectors for each target vector using Target objects    // The default combination strategy is "average"    Target.average(Target.vector("jeopardy_questions_vector", v1),        Target.vector("jeopardy_answers_vector", v2)),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : response.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var response = await collection.Query.NearVector(    // Specify the query vectors for each target vector    vectors: new Vectors    {        { "jeopardy_questions_vector", v1 },        { "jeopardy_answers_vector", v2 },    },    limit: 2,    returnMetadata: MetadataOptions.Distance);foreach (var o in response.Objects){    Console.WriteLine(JsonSerializer.Serialize(o.Properties));    Console.WriteLine(o.Metadata.Distance);}

You can also specify the query vectors as an array of vectors. The array will be parsed according to the order of the specified target vectors.

You can also specify the same target vector multiple times with different query vectors. In other words, you can use multiple query vectors for the same target vector.

The query vectors in this case are specified as an array of vectors. There are multiple ways to specify the target vectors in this case:

The target vectors can be specified as an array as shown here.

Python
from weaviate.classes.query import MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_vector(    # Specify the query vectors for each target vector    near_vector={        "jeopardy_questions_vector": v1,        "jeopardy_answers_vector": [v2, v3]    },    limit=2,    # Specify the target vectors as a list    target_vector=[        "jeopardy_questions_vector",        "jeopardy_answers_vector",    ],    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    return_metadata=MetadataQuery(distance=True)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearVector({  // Specify the query vectors for each target vector. where v1, v2.. are vectors  'jeopardy_questions_vector': v1,  'jeopardy_answers_vector': [v2, v3]}, {  limit: 2,  // Specify the target vectors as a list  targetVector: ['jeopardy_questions_vector', 'jeopardy_answers_vector'],  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
var responseV1 = collection.query.nearVector(    // Pass multiple Target.vector objects with the same name    // The default combination strategy is "average"    Target.average(Target.vector("jeopardy_questions_vector", v1),        Target.vector("jeopardy_answers_vector", v2),        Target.vector("jeopardy_answers_vector", v3)),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : responseV1.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var response = await collection.Query.NearVector(    // Use NearVectorInput to pass multiple vectors naturally    vectors: v =>        v.TargetVectorsSum(            ("jeopardy_questions_vector", v1),            ("jeopardy_answers_vector", v2),            ("jeopardy_answers_vector", v3)        ),    limit: 2,    returnMetadata: MetadataOptions.Distance);

If you want to provide weights for each target vector you can do it as shown here.

Python
from weaviate.classes.query import TargetVectors, MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_vector(    # Specify the query vectors for each target vector    near_vector={        "jeopardy_questions_vector": v1,        "jeopardy_answers_vector": [v2, v3]    },    limit=2,    # Specify the target vectors and weights    target_vector=TargetVectors.manual_weights({        "jeopardy_questions_vector": 10,        "jeopardy_answers_vector": [30, 30],  # Matches the order of the vectors above    }),    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    return_metadata=MetadataQuery(distance=True)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearVector({  'jeopardy_questions_vector': v1,  'jeopardy_answers_vector': [v2, v3]}, {  limit: 2,  // Specify the target vectors as a list  targetVector: jeopardy.multiTargetVector.manualWeights({    "jeopardy_questions_vector": 10,    "jeopardy_answers_vector": [30, 30], // Matches the order of the vectors above  }),  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
var responseV2 = collection.query.nearVector(    // Specify weights for each vector    Target.manualWeights(        Target.vector("jeopardy_questions_vector", 10f, v1),        Target.vector("jeopardy_answers_vector", 30f, v2),        Target.vector("jeopardy_answers_vector", 30f, v3) // Weights match the vectors    ),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : responseV2.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var responseV2 = await collection.Query.NearVector(    vectors: v =>        v.TargetVectorsManualWeights(            ("jeopardy_questions_vector", 10, v1),            ("jeopardy_answers_vector", 30, v2),            ("jeopardy_answers_vector", 30, v3)        ),    limit: 2,    returnMetadata: MetadataOptions.Distance);

Specify target vector names and join strategy

Section titled “Specify target vector names and join strategy”

Specify target vectors as an array of named vectors and how to join the result sets.

The sum, average, minimum join strategies only require the name of the strategy and the target vectors.

Python
from weaviate.classes.query import TargetVectors, MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_text(    query="a wild animal",    limit=2,    target_vector=TargetVectors.average(["jeopardy_questions_vector", "jeopardy_answers_vector"]),  # Specify the target vectors and the join strategy    # .sum(), .minimum(), .manual_weights(), .relative_score() also available    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    print(o.metadata.distance)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearText('a wild animal', {  limit: 2,  targetVector: jeopardy.multiTargetVector.average(['jeopardy_questions_vector', 'jeopardy_answers_vector']),  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
CollectionHandle<Map<String, Object>> collection =    client.collections.use(COLLECTION_NAME);var response = collection.query.nearText(    Target.average("a wild animal", "jeopardy_questions_vector",        "jeopardy_answers_vector"), // Specify the target vectors and the join strategy    // .sum(), .min(), .manualWeights(), .relativeScore() also available    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : response.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var collection = client.Collections.Use(CollectionName);var response = await collection.Query.NearText(    query =>        query(["a wild animal"])            // Specify the target vectors and the join strategy            // Available: Sum, Minimum, Average, ManualWeights, RelativeScore            .TargetVectorsAverage("jeopardy_questions_vector", "jeopardy_answers_vector"),    limit: 2,    returnMetadata: MetadataOptions.Distance);foreach (var o in response.Objects){    Console.WriteLine(JsonSerializer.Serialize(o.Properties));    Console.WriteLine(o.Metadata.Distance);}

Search by sums of weighted, raw distances to each target vector.

The weighting in detail

Each distance between the query vector and the target vector is multiplied by the specified weight, then the resulting weighted distances are summed for each object to produce a combined distance. The search results are sorted by this combined distance.

Python
from weaviate.classes.query import TargetVectors, MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_text(    query="a wild animal",    limit=2,    target_vector=TargetVectors.manual_weights({        "jeopardy_questions_vector": 10,        "jeopardy_answers_vector": 50    }),    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    print(o.metadata.distance)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearText('a wild animal', {  limit: 2,  targetVector: jeopardy.multiTargetVector.manualWeights({    jeopardy_questions_vector: 10,    jeopardy_answers_vector: 50,  }),  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
CollectionHandle<Map<String, Object>> collection =    client.collections.use(COLLECTION_NAME);var response = collection.query.nearText(    Target.manualWeights("a wild animal",        Target.weight("jeopardy_questions_vector", 10f),        Target.weight("jeopardy_answers_vector", 50f)),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : response.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var collection = client.Collections.Use(CollectionName);var response = await collection.Query.NearText(    query =>        query(["a wild animal"])            .TargetVectorsManualWeights(                ("jeopardy_questions_vector", 10),                ("jeopardy_answers_vector", 50)            ),    limit: 2,    returnMetadata: MetadataOptions.Distance);foreach (var o in response.Objects){    Console.WriteLine(JsonSerializer.Serialize(o.Properties));    Console.WriteLine(o.Metadata.Distance);}

Search by sums of weighted, normalized distances to each target vector.

The weighting in detail

Each distance is normalized against other results for that target vector. Each normalized distance between the query vector and the target vector is multiplied by the specified weight. The resulting weighted distances are summed for each object to produce a combined distance. The search results are sorted by this combined distance.

For a more detailed explanation of how scores are normalized, see the blog post on hybrid relative score fusion

Python
from weaviate.classes.query import TargetVectors, MetadataQuerycollection = client.collections.use("JeopardyTiny")response = collection.query.near_text(    query="a wild animal",    limit=2,    target_vector=TargetVectors.relative_score({        "jeopardy_questions_vector": 10,        "jeopardy_answers_vector": 10    }),    return_metadata=MetadataQuery(distance=True))for o in response.objects:    print(o.properties)    print(o.metadata.distance)
JavaScript/TypeScript
jeopardy = client.collections.use('JeopardyTiny');result = await jeopardy.query.nearText('a wild animal', {  limit: 2,  targetVector: jeopardy.multiTargetVector.relativeScore({    jeopardy_questions_vector: 10,    jeopardy_answers_vector: 10,  }),  returnMetadata: ['distance'],});result.objects.forEach((item) => {  console.log(JSON.stringify(item.properties, null, 2));  console.log(JSON.stringify(item.metadata?.distance, null, 2));});
Java
CollectionHandle<Map<String, Object>> collection =    client.collections.use(COLLECTION_NAME);var response = collection.query.nearText(    Target.relativeScore("a wild animal",        Target.weight("jeopardy_questions_vector", 10f),        Target.weight("jeopardy_answers_vector", 10f)),    q -> q.limit(2).returnMetadata(Metadata.DISTANCE));for (var o : response.objects()) {  System.out.println(objectMapper.writerWithDefaultPrettyPrinter()      .writeValueAsString(o.properties()));  System.out.println("Distance: " + o.queryMetadata().distance());}
C#
var collection = client.Collections.Use(CollectionName);var response = await collection.Query.NearText(    query =>        query(["a wild animal"])            .TargetVectorsRelativeScore(                ("jeopardy_questions_vector", 10),                ("jeopardy_answers_vector", 10)            ),    returnMetadata: MetadataOptions.Distance);foreach (var o in response.Objects){    Console.WriteLine(JsonSerializer.Serialize(o.Properties));    Console.WriteLine(o.Metadata.Distance);}

Have a question or feedback? Here's how to reach us.

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu